initial git creation

This commit is contained in:
PSYC 2009-03-03 04:27:01 +01:00
commit 2ede0de60e
278 changed files with 230984 additions and 0 deletions

19
.gitignore vendored Normal file
View File

@ -0,0 +1,19 @@
CVS
.config
~$*
.DS_Store
.metadata
.actionScriptProperties
.#*
world/net/place/_*.c
world/net/include/place.i
*~
*.swf
*.swp
*.rej
*.log
*.pem
*old
*bak
*diff
*orig

73
ANNOUNCE Normal file
View File

@ -0,0 +1,73 @@
CODE RELEASE: [lpmud driver] psyclpc 4.0.6 - derivate of LDMud
ladies & gentlemen,
wanted to inform you in accordance with Lars we have started shipping
our own LDMUD distribution as it was getting just too complicated to
maintain all necessary patches in our installation procedure for the
psyced server (multi-protocol chat/messaging server).
wrapping up our own tars has simplified distributing psyced a lot.
we also dared to change the name (1) to make it less confusing for
our users that "ldmud" belongs to "psyced" and (2) not to have to
fulfil the high expectations you would put into an LDMud product. ;)
psyclpc is a derivate of ldmud 3.3.714 (the current version in the
ldmud repository since over a year) with the following changes:
1. The driver has been modularized in such a way that you can turn
each function, many of them typically needed for MUD use, on or
off. The optional modules are:
* actions (MUD command parser)
* built-in editor 'ed'
* inventories, environments and light
* paranoid reference checks
* shadowing
* socket snooping
* swapping
Turning any of these off makes your driver lighter and faster,
which is quite nice. ;)
2. New optional packages have been added:
* expat XML parser
* DNS SRV resolution
* JSON parser
* automatic localhost telnet authentication via /proc.
3. TLS support has been improved a lot.
4. Minor fixes concerning 64 bit compilation, Solaris compilation,
UTF-8 support, outgoing connections and multi-homed connects for
dynamic DNS.
5. Debugging message style has been revamped and the secondary debug
log made optional, but you can switch it back to ldmud compatible
whenever you want.
6. All new functions are neatly configurable using the settings files
introduced by LDMud.
all in all no big deal, but it is being run in various places and
seems to perform flawlessly, so that in itself is nice (the bugfixes
submitted on mantis are really good!).
we didn't remove anything of the MUD support, just made it all optional
and configurable, so you can still run an LPMud on this. there is even a
new field in the configure.in letting you put the "ldmud" name back in
place, or whatever you want your driver to call itself. :)
by the way, you may be interested that the psyced's "mudlib" is architected
in a way that you can merge it into an existing mud. this brings PSYC, XMPP,
IRC, RSS and several other features into your system - there has even been
an experimental adaption of intermud over PSYC.. sort of an intermud 4.
here are all the links:
psyclpc http://lpc.psyc.eu
psyced http://www.psyced.org
psyc http://about.psyc.eu
questions? telnet psyced.org

116
CHANGELOG Normal file
View File

@ -0,0 +1,116 @@
2008-05-28 (fippo/lynX) (4.0.8)
+ new efuns:
string strftime(string, int default: F_TIME);
int strptime(string, string);
+ temporary efun tls_want_peer_certificate()
- SSL_set_shutdown() hopefully fixes openssl crasher on SSL_ERROR_SYSCALL
2008-01-21 (fippo) (4.0.7)
+ new enable_binary() efun to allow for binary networking (EXPERIMENTAL)
+ new ieee754_to_string(float) and string_to_ieee754(string)
efuns to support this specific flavour of floating point notation
2008-01-12 (fippo)
- fixed erq SRV support on 64 bit architectures
2008-01-02 (lynX)
- repaired builtin pcre utf8 support
+ use builtin pcre by default until utf8 support becomes more popular
in distributions (can be an unnecessary complication otherwise)
2007-10-07 (Lars)
- foreach(int i: <num>) recognizes if <num> is negative
and throws an error. (Bug #503, from ldmud)
- (configure) When testing for libiconv, reference a real libiconv method.
This catches situations where libiconv exists, but is of the
wrong architecture.
2007-08-29 (lynX) (4.0.6)
+ #define USE_RESTORED_OBJECTS in object.c teaches
save_object() to store object names using a `name` syntax and
restore_object() to put it back in circulation in form of strings.
+ enable_use_restored_objects activates this (but we don't use it yet)
+ erq now terminates peacefully whenever the driver shuts down
- cleaned up a lot of debug output behaviour and put it into
#ifdef VERBOSE and #ifdef USE_LDMUD_COMPATIBILITY
+ enable_use_debug_log=no sends all debug output to stdout
- enable_backtrace_always and enable_ldmud_compatibility
replaced by enable_use_ldmud_compatibility
- replaced enable_use_paranoid_refs by enable_use_paranoia which now
also ifdefs the "strict checks" code
+ added enable_use_experimental
+ EXPERIMENTAL: send TLSv1 handshake when acting as TLS client
2007-08-19 (lynX) (4.0.5)
+ enable_use_builtin_editor=no disables the built-in text editor 'ed'.
+ enable_use_inventories=no removes all MUD-related functionality
concerning inventories and environments.
+ enable_use_snooping=no disables all socket snooping code.
+ enable_use_actions=no disables all MUD-style command parser facilities.
+ enable_use_socket_limits=no disables limits on amount of entered lines
per second including get/set_max_commands() efuns.
+ enable_use_shadowing=no disables various forms of shadowing.
+ enable_use_swap=no disables the ability to swap program bytecode to disk.
+ enable_use_paranoid_refs=no disables paranoid runtime checks, you only
need this if you are making dangerous changes to the driver code
or looking for mysterious crashes.
+ enable_ldmud_compatibility=no mostly affects unnecessary debug messages
which will otherwise appear for maximum compatibility.
+ optimized outconn management with num_pending_outconns & extra_jobs_to_do
2007-08-16 (lynX) (4.0.4)
+ added detection of #include <arpa/nameser_compat.h> which seems to
determine the availability of DNS SRV extensions
- erq will be compiled without SRV instead of failing to compile
+ __NO_SRV__ is added to the predefines in lex.c if SRV is unavailable
+ enable_backtrace_always=yes stops the stupid behaviour of hiding away
backtraces in the debug log (the debug log should only be necessary
for driver developers, not lpc coders). It doesn't have to be like php,
where the end user sees the full backtrace, but at least the admin should
be considered sufficiently competent. :)
+ new RE_UTF8 flag mirrors the PCRE_UTF8 flag and allows operating on
unicode character ranges using regexps.
2007-07-06 (lynX) (4.0.3)
+ added zippo's 64 bit patches. apparently do not break 32 bit architectures.
thx to Casey Zacek; Zippo @ EotL; mud.eotl.org 2010
2007-05-07 (lynX) (4.0.2)
+ moved program name ('psyclpc' formerly 'ldmud') into configure.in
2007-05-04 (lynX) (4.0.2)
- fixed a compilation problem on Solaris derivates
+ added authlocal
+ added --with_max_net_connects, --with-size_socket_buffer
and forced settings when running ./configure without args
- applied http://mantis.bearnip.com/view.php?id=472 to fix zero byte
output in tell_object(), tell_room() and say()
+ fixed multihomed connect to improve dynamic dns support
2007-05-03 (fippo) (4.0.1)
- removed TLS CRL implementation as it isn't being used currently
and crashes on some systems
2007-04-17 (lynX) (4.0.0)
+ using new major version number to avoid conflicts with LDMUD.
2007-04-08 (lynX)
- removed doc, mud, src/util/xerq, HISTORY, src/settings.
- crippled CHANGELOG.
- updated COPYRIGHT and README.
+ created new CVS and introduced the pragmatic name 'psyclpc'
- some values adjusted to heavy networking use
2007-02-16 (fippo)
- TLS fixed
+ support for TLS CRLs
+ JSON (javascript object notation) efuns
- set_combine_charset allows newline and null to be combined
- some minor patches
+ pkg-expat
2006-07-09 (Lars Duening) (3.3.714)
- Created snapshot.
For prior CHANGELOG and HISTORY see the LDMud distribution.

481
COPYING.LIB Normal file
View File

@ -0,0 +1,481 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

77
COPYRIGHT Normal file
View File

@ -0,0 +1,77 @@
psyclpc, an LDMud with a couple of patches and optimizations for psyced.
Patched by fippo and lynX.
Our patches usually also merge into LDMud eventually.
LDMud, a LPmud gamedriver.
Copyright 1997-2006 by Lars Duening.
LDMud is based on LPmud, which is
Copyright 1989-1991 by Lars Pensjö, and, starting with version 3.1.2,
Copyright 1991-1997 by Joern Rennecke.
These copyrights notices are actually incorrect, as each of the many
authors below is still owner of his or her copyright. Also, since about
1990, LPmud contains GPL code, making the original restrictive licensing
scheme invalid. At the same time the COPYLEFT was added, which is now
to be considered the only viable licensing scheme for LPmud and its
derivates.
Ever from the start LPMud used the GNU malloc implementation, it
was thus never fit to become restricted from GPL-incompliant use.
The only code in this driver which originates from the CD driver is
the UDP implementation. In 1993 Jacob Hallen <jacob@cd.chalmers.se>
writes "The UDP stuff is to be considered public domain."
------------------------------------------------------------------------
LDMud contains contributions of many volunteers as listed in the file CREDITS.
Of these, the following packages are subject of their own copyright when
used outside the context of this gamedriver; please refer to the appropriate
files for details.
The regexp package is based on the code written by Henry Spencer.
The portable crypt() implementation is Copyright by Eric Young.
The smalloc allocator was written by Sean T. Barrett and put into the
public domain.
The 'ed' editor (with the exception of the indentation code) is Copyright
by Brian Beattie, Kees Bot and others.
The non-corrupting indentation code for the 'ed' editor was written and
contributed by Felix A. Croes (<felix@dworkin.nl>) from his DGD gamedriver.
The sprintf() efun was written by Sean A. Reith and put into the public
domain.
All code taken from the MudOS driver is Copyright by Tim Hollebeek and
the original authors. Use for other purposes than LPmud drivers or under
licenses significantly different from the original LPmud license needs
explicite permission.
The random() efun is implemented using the Mersenne Twister generator which is
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, and subject
to a BSD-style license. The implementation is the faster implementation based
on Shawn Cokus and Matthew Belle's improvements. See random.c for the full
text of the license.
The MD5 message digest algorithm is Copyright (C) 1991-2, RSA Data Security,
Inc.
The Apache-compatible MD5 password encryption is Copyright (C) 2000 Apache
Software Foundation.
The PCRE (Perl Compatible Regular Expression) is Copyright (C) 1997-2001 by
Philip Hazel. LDMud contains just the files required for the driver (with
small modifications); see pcre/LICENCE for the licence terms and the location
of the full package, and pcre/README.LDMUD for an explanation of the changes.
The lpc-mode.el for EMACS is Copyright (C) 2002 Vivek Dasmohapatra
<vivek@etla.org>, and distributed under the GPL.
The PostgreSQL package is based on code written and donated 2001 by Florian
Heinz.
The MCCP implementation was originally written for Finalfrontier by
Bastian Hoyer.

281
CREDITS Normal file
View File

@ -0,0 +1,281 @@
The program was originally written by
Lars Pensj|, April 1989 (lars@cd.chalmers.se (no longer valid)).
Lars gives the following credit:
The regexp package was made by Henry Spencer.
The ed package was not done by me. See the file ed.c for information.
Bit manipulations was implemented by pell@lysator.liu.se who also found
several bugs that had eluded me for months.
Valuable help and hints from: Mark Nagel, James Seidman, Moonchilde and more.
Roland Dunkerley III fixed for-loops, do-while and the operators ++ and --.
Sean T Barrett made smalloc.c.
Lennart Augustsson convinced me to implement a compiler for a virtual
stack machine. He also implemented the built-in preprocessor.
John S. Price found and fixed many bugs.
The shadow idea was "forwarded" to me by John S. Price from Team Cthulhu
(Bill Burdick, Roy Riggs, Mitch Adler).
Michael Malone, Michael O'Reilly, Klaus Rennecke, J|rn Rennecke and
Germano Caronni found and fixed a large amount of bugs.
Petri Wessman fixed changes for SCO unix and AIX.
-----------------------------------------------------------------------------
Joern Rennecke ( amylaar@cs.tu-berlin.de ) gives this credit:
The non-corrupting indentation code for ed was written by Felix A. Croes,
aka Dworkin (<felix@dworkin.nl>) and originates from his DGD.
Mud-sprintf() is from Lynscar (Sean A Reith, <gusar@uniwa.oz.au> and
was donated into the Public Domain.
The alist based mapping implementation was supplied by Dworkin.
The idea for query_actions and an implementation that has been partially used
is from Peter Eriksson (aka lpd) pen@lysator.liu.se
The port to Amiga was done by Mateese ( Lars Duening )
The udp connectivity is from the CD driver, and was fitted in by deepthought.
Demos, Freaky, Hurl, Hyp, Mateese, Pepel and Jof did a lot of alpha
testing.
Reimer Behrends located a lot of bugs. He also supplied a portable macro to
test numbers for having but a single bit set, a mergesort based
sort_array() and variadic function support.
get_object_actions() was supplied by herp.
Marcus Meissner found and fixed many bugs.
Carl White, Mark (ec179@city.ac.uk), Archimedes (Robert Fuller), Eric Blade,
Mitchell Brandsma, Sam Bobroff, Jim Cogbill, Ben Fennema,
Sorva (Ed Zielinski), Loke@Wonderland (Solem), Claus S. Jensen, Nils Magnus,
samo@MorgenGrauen, Frobozz (Bryan Schuler), Sique@Nightfall, APJ,
Deathknight, Tero Jyri Michael Pelander (tpeland@utu.fi),
Willem van der Oord (willem@marble.dcr.net), Hate@MorgenGrauen,
Bob Farmer, Randor@EoP, Trevor Phillips, Robert M. Zigweid, Inspiral,
Brian Gerst, Rasmus H. Hansen, Demodian (John Kurtz), William J. Burton,
Patrick Li, Niilo Paasivirta, Frank Stolze, Penelope@Avalon,
Nathan@Unholy Lands, mubo@SiliconDream, Sunblood@Tubmud, Alfe@Tubmud,
Tatu Saloranta, Chameloid@Tubmud and Martin Brenner (deepthought) reported bugs.
Foslay did the OS/2 port.
Ray Gilbert originally did the MSDOS port, which was modified later by
Rasmus Hellbug Hansen.
Marcus Meissner contributed regreplace().
Slider@Tubmud supplied GnuWin32 patches.
-----------------------------------------------------------------------------
Lars Duening thanks:
- Dana Durkee and the magnificient Wessex for enhancing my life.
- the citizens of One Step Beyond, PK-Mud and UNItopia for enduring my
driver experiments.
- Malcom Tester (malcom.tester@comcast.net) for providing me with access to
a Solaris system for testing.
- Elric (elric@lpmud.com) for providing me with access to
a FreeBSD system for testing.
- Blackcat (?) for providing me with access to a Linux system for testing.
- Freaky for providing me with access to an Irix system for testing, numerous
bug reports, and lots of patience when new versions crashed even faster
than the old ones.
- Kees Leune for providing me with access to a Linux/Sparc system for
testing.
- Stefan Petri and contributors for the extensive documentation of the
Amylaar driver (see also doc/README).
- the MudOS programmers for the efun terminal_colour() and Michael Schaefer
for adapting it for LDMud.
- Martin Brenner: initial multi-port implementation, inetd compatibility
code.
- Brian Gerst (bgerst@quark.vpplus.com) for the xerq daemon.
- Reinhard Pfau (Reinhard.Pfau@unix-ag.org, Mubo@SiliconDream) brought
the autoconf mechanism up to date.
- Ron Koerner (ron.koerner@gmx.de, Righ@FinalFrontier) provided the
initial implementation of inline closures modelled after MudOS' syntax.
- Uwe (uwe@6bone.informatik.uni-leipzig.de) provided the basic IPv6 support.
- Mark Daniel Reidel (Karm@Nightfall) did the first implementation of
the mySQL efuns.
- Dennis VanHoey (devanhoe@usol.com) did the compiling and testing for the
Darwin port.
- Bart van Driessche (bart@multi.franken.de, Hunter@FinalFrontier) did the
new OS/2 port.
- Menaures added the tab character conversion to the editor, and gleefully
found new ways to crash the driver.
- Adam Helps donated the LPC implementation of the A* pathfinding algorithm.
- Christian Welzel adapted ptmalloc (a threadsafe variant of Doug Lea's
allocator) for LDMud and extended it to support garbage collection.
- for bug reports, critics, fixes, patches and other support:
Adam Helps (ahelps@cs.byu.edu, acius@simud.org)
Alex@TubMud (at16@st-andrews.ac.uk)
Alexander Fetke (alfebtcd@cs.tu-berlin.de, Alfe@Tubmud)
Alexander Dobrinescu (ad@artifacts.de, Lev@FinalFrontier)
Anders Strandloev Elkjaer (ase@cs.auc.dk)
Andre Meiske (guandalug@magellan.tat.physik.uni-tuebingen.de)
Andreas Grammlich (andreas.grammlich@prepress.de, Gum@Wunderland)
Andre Grosse (ag17@irz.inf.tu-dresden.de, Patryn@Morgengrauen)
Andreas Fischer (andreas.fischer@physik.tu-chemnitz.de)
Andreas Klauer (menaures@metamorpher.de, Menaures@Unitopia)
Andreas Weller (aw6@informatik.uni-ulm.de, Zwirch@Carledon)
Andres Cvitkovich (ac@twig.mond.at, ac@zwerg.at, Woody@Silberland)
Andrew Weisz (elarke01@snet.net)
Andy Zeneski (jaz@zsolv.com)
Arne @ Elridion
Athanasia Steele (azurite@mail1.nai.net)
Baba@Avalon
Bastian Hoyer (hoyer@wisc.de, dafire@dafire.de)
Ben Fennema (bfennema@ix.netcom.com)
Bertram Felgenhauer (bf3@irz.inf.uni-dresden.de, Fuchur@Wunderland)
Bill Andrulonis (bill.andrulonis@citrix.com, Bofin@Realmsmud)
Billy Pembroke (wpem@comcast.net)
Blackcat@PK-Mud (amuelle1@htwm.de)
Brandon (pothole@darkspyre.quad.net)
Brandon Mathis (brandon.mathis@medsolutions.com)
Bruce Mitchell (mitchell@manly.delconet.com, Klahn@Manly Mud)
Carlo v. Loesch (psyc://psyced.org/~lynX)
Carsten Pluntke (su0289@studserver.uni-dortmund.de, Vejar@ForgottenDreams)
Casey Zacek (cz@netspire.net, zippo@eotl)
Chris Bender (chris.bender@attbi.com)
Christian "Leonidas" Becker (cbecker@informatik.hu-berlin.de)
Christian Fiedler (fido2@gmx.net)
Christian Kirschbaum (chrissy@cs.tu-berlin.de, Chameloid@Tubmud)
Christian Mudra (c_mudra@informatik.uni-kl.de, Coogan@Tubmud)
Christian Welzel (gawain@wh9.tu-dresden.de, Sir_Gawain@camlann.de,
Gawain@Regenbogen)
Craig Venz (Craig Venz@citrix.com, Kilan@Realmsmud)
croft@UNItopia.rus.uni-stuttgart.de
Collin Baillie (sanac@optushome.com.au)
Dale "Elric" Perkins (dale_perkins@mac.com, dale@lpmud.com)
Daniel von Dincklage (daniel@ozet.de, Sunblade@SiliconDream),
Daniel Fischer (dfischer@gmx.de, Dan@Gueldenland)
Daniel Sloan (sloand@alphalink.com.au)
Daryth Kendrickson (stavros@deadofnight.com)
David Gibbs (ishara@btinternet.com)
David 'Greyelk' Gibby (oop_apprentice@yahoo.com)
Dennis VanHoey (dvanhoe@usol.com)
Derek Baron (dbaron_ks@hotmail.com)
Dominik Zanettin (zhan@opossum.htu.tuwien.ac.at, Zhan@Beutelland)
Edward S. Marshall (esm@logic.net)
Enrico Bauermeister (ebauermeister@t-online.de, Enrico@FinalFrontier)
Eivind (ekj@ekj.vestdata.no)
Erik Meusel (emeusel@prinz-atm.CS.Uni-Magdeburg.De)
Fantom (Fantom@Tharsis-Gate.org)
Fini Jastrow (Fiona@Wunderland, ujastrow@mail.desy.de)
Florian Heinz (ctx@amail.dereference.de)
Frank Kirschner (freaky@unitopia.uni-stuttgart.de)
Frank Stolze (fstolze@iName.com)
Frank Syse (syseworks@mac.com)
Gerhard Schmidt (estartu@augusta.de)
Gimli@Unitopa (gimli@schlumpf.net)
"Gnomi" (gnomi@UNItopia.rus.uni-stuttgart.de)
Gunnar Kreitz (gunnark@chello.se)
Heiko Kopp (hkopp@informatik.uni-rostock.de, bardioc@bardioc.com,
Bardioc@Evermore)
Henk Stokhorst (Tha@wxs.nl)
Holger Kremss (jur94ewp@studserv.uni-leipzig.de, Holger@web.de,
Holger@Wunderland)
Jaroslaw Sitek (aron@bobas.nowytarg.pl)
Jason Hitt (jhitt25@swbell.net)
Jean-Stephane Jokeit (jokeit@gmx.de, xtian@avalon)
Joern Rennecke (amylaar@cygnus.co.uk)
Jose Manuel Roman (roman@wol.es, Theuzifan uzi@simauria.upv.es)
Joseph Graham (randalar@earthlink.net)
Josh Rollyson (jrollyson@sosdg.org)
Juergen Weickert (Sissi@UNItopia)
Karl N. Matthias (karmat@matthias.org)
Kathrin Paschen (paschen@ira.uka.de)
Kees Leune (c.j.leune@kub.nl)
Kent Chilson (kentiepoo@hotmail.com)
Kirnan@Avalon
Krystal-Anne Rubenstein (punkette@hotmail.com)
Kirnan@Avalon
Largo@Wunderland (emeusel@csmd.cs.uni-magdeburg.de)
Lasse Fuglsang Pedersen (volmer@qeep.dk, Zordiac@DeeperTrouble2)
Lee Salzman (lee.salzman@lvdi.net)
Logic (logic@logic.net)
"Mammi" (mammi@unitopia.uni-stuttgart.de)
Manu Mäki (mtmaki@pultti.turkuai.fi, Cendor@Winterkill)
Mark Daniel Reidel (Karm@Nightfall,
reidelm@rbg.informatik.tu-darmstadt.de)
Markus Peter (warp@spin.de, warp@hip.spin.de)
Martin (mandragon@morgengrauen)
Mat@Maethos
Mats Carlberg (matca@lysator.liu.se)
Matthew Julius (julius.2@wright.edu)
Michael Fedrowitz (mfedrowi@ix.urz.uni-heidelberg.de,
Michael_Fedrowiz@gmx.net, Rhodry@ForgottenDreams)
Michael Sporn (sporn@mathematik.hu-berlin.de, sunblood@tubmud)
Mike Conley (mpc@sgi.net, Tamarindo@Sovereign)
mudder@Furtual.ORG
"Nathan@Unholy Lands" (mud@pc181.iaee.tuwien.ac.at)
Neil McBride (neil@castinian.org)
Nepomuck@UNItopia
Nick Derewianka (nickd@e-media.com.au)
Nico Ehemann (n.ehemann@wzl.rwth-aachen.de)
Niels Boehm (bohmmrwc@minet.uni-jena.de, Mariko@Regenbogen)
Nuutti Kotivuori (naked@iki.fi)
Oskar Linde (d98-oli@nada.kth.se)
Parsec
Patrick May (patrick.may@cedelgroup.com)
Paul Apgar (tiresius@usa.net, tiresius@Cosmos)
Philipp Hancke (psyc://goodadvice.pages.de/~fippo)
Rainer Doerntge (rainer.doerntge@dlh.de)
Rajko Albrecht (ral@alwins-word.de, Alwin@Avalon)
Ralph (ralphi@vkr.k-net.dk)
Ralph Zitz (RZ@zitz.dk, Nostradamus@OSB)
Reimer Behrends (Macbeth@Tubmud)
Reinhard Pfau (reinhard@netlab1.hrz.uni-siegen.de, mubo@SiliconDream),
Reinhard Vicinus (vicinus@rhrk.uni-kl.de, Risky@Unitopia)
"Remsgost" (remsgost@blitzstrahl, radm@remsnet.de)
Robb Townsend (meecham@infonline.net)
Robert Forshaw (postmaster@rbf.org.uk)
Robert Reither (mud@klein.htu.tuwien.ac.at, Nathan@Unholy.Lands)
Robert Treml (robert@des.glaubst.net)
Rodney Quaye (sark@oberon.krans.com)
Ron Dawson (rondawson@syd.eastlink.ca, rdawson@cgc.ns.ca, Caper@PixieMud)
Sebastian Huss (huss@informatik.hu-berlin.de, baba@avalon)
Shinarae Lluminus@Batmud (shinarae_lluminus@hotmail.com)
Slava "DieHARD" Ignatjev (root@impar.com, slava@intersfera.lt)
Sieni (sampsa@netsonic.fi)
Simon Fischer (firebat@redcrown.de)
Stefan Budweiser (Stefan.Budweiser@compaq.com)
Stefan Riemer (stefan.riemer@bauing.uni-weimar.de, Peng@FinalFrontier)
Stephan Lichtenhagen (lichti@amethyst.chemie.uni-dortmund.de,
stephan@lichtenhagen.de, Tiamak@Morgengrauen)
Steve Goucher (su2996@eclipse.co.uk)
Steve Willoughby (steve@alchemy.com, Ragnarok)
Tatu P. Saloranta (doomdark@cc.hut.fi)
Terry Penn (terry@simaril.net)
TheFinn (thefinn@ar.com.au)
Thomas Feldmeier (tfeldmei@student.informatik.uni-ulm.de, Zora@Carledon,
zora@alpha.universalware.de)
Thorsten Klose (Thorsten.Klose@infineon.com, Avatar@avalon)
Tiberian@Unitopia
Tmm@UNItopia? (Tmm@gmx.de)
Tobias Josefowitz (tobij@goodadvice.pages.de)
Tomas (Vandergnome@aol.com)
Tomi Valkeinen (tomi.valkeinen@taikatech.com, Tomba@Batmud)
Tucita@UNItopia
Urv (urv@hispeed.ch)
Volker Behr (Sorcerer@AbendDaemmerung, vrbehr@cip.physik.uni-wuerzburg.de)
Wayne Woods (w.woods@optusnet.com.au)
Willem van der Oort (willem@dcr.net)
Wolf Dieter Dallinger (Pulami@Unitopia, wolf.dieter@dallinger.de)
Zonk@FinalFrontier (zonk@finalfrontier.mud.de, rueschi@berit-broese.de)
The Wizards of Evermore

22
FAQ Normal file
View File

@ -0,0 +1,22 @@
===============================================================================
Why our own derivate of the LDMud?
* Expecting our psyced admins to find a suitable version made installation
unnecessarily complicated, and every now and then an ldmud release does
indeed not work for psyced.
* We love the work mateese has been doing and still does, and we will
surely continue to share all gotchas and improvements so that both
variants of LDMud strive. Only we catch ourselves needing to have a
shorter change inclusion and release cycle. We asked mateese before
taking this step.
* For that reason we had been making the psyced install procedure too
complicated, as it was always trying to patch some things in the ldmud
source, even when it didn't know which ldmud version it was working on.
* Now to have psyced and its driver bundled in a pair which is safely known
to be happily working together is a simple yet great step forward.
* This makes the whole psyced installation base more homogeneous. We don't
have to deal with deployed instances that do not properly do this or that.
It should still be possible to run psyced with an off-the-mill ldmud and
counterwise run a MUD installation with a psyclpc.
===============================================================================

21
HELP Normal file
View File

@ -0,0 +1,21 @@
[CONTACT]
psyclpc is being maintained by fippo & lynX.
fippo is available at psyc://goodadvice.pages.de/~fippo
or xmpp:fippo@goodadvice.pages.de
lynX is available as psyc://psyced.org/~lynx
You can reach us at psyc://psyced.org/@welcome
[HISTORY]
psyclpc is a programming language for intense multi-user network applications
such as psyced. it's a recent fork of LDMud with some features and many
bug fixes. we kept it compatible to LDMud, so you can run a MUD with it, too.
It is available from <http://lpc.psyc.eu>.
LDMud itself is a continuation of the Amylaar LPMud Gamedriver 3.1.2.
See also <http://www.bearnip.com/lars/proj/ldmud.html>.
psyclpc is released under the GNU LIBRARY GENERAL PUBLIC LICENSE, Version 2.

323
INSTALL Normal file
View File

@ -0,0 +1,323 @@
Topics covered:
- psyclpc & LDMud Notes
- Unix or Unix-like systems, with additional details for FreeBSD, AIX 3.4,
and DEC Ultrix.
- IPv6
- mySQL
- BeOS
- Windows 95/98/NT
- OS/2
psyclpc & LDMud Notes
---------------------
psyclpc is a variant of the LPC language optimized for psyced.
When using this driver distribution "./configure" will restart
itself as "./configure --with-setting psyced". This will run
configure with all the sane options necessary for a pleasant
psyclpc experience tuned to psyced requirements.
See also http://lpc.psyc.eu and http://about.psyc.eu/psyclpc
Should you want to make a very traditional driver close to the
LDMud original instead, copy your own settings file to the
settings directory and run it. All the new functions of psyclpc
will then automatically default to LDMud-compatible behaviour.
Also running "./configure" with *any* parameters will keep it
from loading psyced behaviour. Expect psyced not to work with
such a driver. It will probably fail with one of these messages:
psyclpc: Unknown option '--tls-key'.
Failed to load master object 'secure/master'.
Unix or Unix-like system
------------------------
The driver uses a standard autoconfiguration system which on most
systems does all the work for you (for exceptions see below).
To prepare the compilation, execute the 'configure' script from
within the src/ directory.
configure checks for a number of site specific settings and uses this
information to create the files machine.h (from machine.h.in), Makefile
(from Makefile.in) and config.h (from config.h.in). We'll come back to
config.h below.
configure takes a lot of arguments (--help will tell you everything),
but the most important are these:
--prefix=PREFIX: the base directory for the mud installation,
defaults to /usr/local/mud .
--bindir=DIR: the directory to install the executables in,
defaults to ${PREFIX}/bin .
--libdir=DIR: the directory where the mudlib is found,
defaults to ${PREFIX}/lib .
--includedir=DIR: the directory where driver's LPC include files
are supposed to live.
defaults to ${PREFIX}/include (which is usually wrong).
--libexecdir=DIR: the directory where the programs for the ERQ are found,
defaults to ${PREFIX}/libexec .
These settings are written into the Makefile and compiled into the driver,
just the mudlib directory setting can be changed with a commandline
argument.
A lot of the drivers parameters can be tweaked for better performance; these
parameters are defined in config.h . This file too is created by configure,
which provides sensible defaults for all parameters for which no explicite
setting is provided. To tweak a setting yourself, pass the argument
'--enable-<option>=yes|no' resp. '--with-<option>=<value>' to configure on
the commandline.
Alternatively, the indivial specifications can be collected in a settings
file, which is stored in the directory src/settings/. To use the
setting file <osb>, give '--with-<osb>' as argument to configure. The
file src/settings/default documents the available settings. The setting
files are self-executing: './settings/<foo> [<extra-configure-args>]' will
start configure with the proper commandline arguments.
The following environment variables can be used to tweak the behaviour
of the configure script:
CC: the name of the C compiler
CFLAGS: compiler flags to be used during the configure script
EXTRA_CFLAGS: compiler flags to be used when compiling the game driver
LDFLAGS: linker flags to be used by configure and for linking the
game driver.
After configuration is finished, you may want to modify the Makefile
to fine tune those parameters which are not covered by the configuration.
The compilation is done using make. Following targets are implemented:
<none>: compile the driver, named 'psyclpc'.
install: compile the driver and install it in ${bindir}
utils: compile the utilities, especially the ERQ demon
install-utils: compile and install the utilities in ${bindir}
install-headers: install the driver header files in ${includedir}.
install-all: compile and install everything.
To actually run this, you need either psyced or a mudlib.
pthreads:
If your systems supports pthreads, --enable-use-pthreads will allow to
compile the driver with pthread support. Currently this means that
background threads will be used to write data to the network.
WARNING: pthreads support is still experimental and might crash
your driver!
FreeBSD:
When using gcc, it could happen that the compiler aborts with signal 10
or 11. The reasons are unknown, but you can restart the compilation
process by typing "make" again (and again...).
AIX 3.4:
The native compiler comes in several forms, of which only the
basic form 'xlc' works with the configuration script.
Start the script as:
CC=xlc ./configure ...
DEC Ultrix:
Depending on the system configuration you might be unable to
compile 'interpret.c' with any kind of optimization at all.
The typical symptom is a failure during the compilation with
"Error code 1". When that happens, do the following steps:
- Make as usual until the "interpret" compilation
fails. The symptom is "Error code 1".
- Edit the makefile. Uncomment the compilation
line for debugging, and comment the compilation
line containing the optimization switches and
options.
- Start the make again. After the "interpret"
compilation completes, control-C out of the
compilation.
- Edit the makefile again. Re-comment the line
for debugging, and uncomment the line with
the optimization switches and options.
- Start the make again. This time it will
complete as expected.
IPv6
----
If your machine supports IPv6, the driver can be configured to use it: give
'--enable-use-ipv6=yes' as argument to the configure script.
Beware: the driver support is rudimentary, experimental, and may cease to
function on the next full moon. Additional work is necessary to really
change _all_ address-related functions in driver and mudlibs.
IPv6 support was implemented by Uwe <mai94cch@studserv.uni-leipzig.de>.
In order to test IPv6 under Linux you need a 2.2.x kernel (preferably 2.2.10
or better) and the inet6 apps. If you use glibc 2.0, you need version 0.35
of the inet6 apps, or for glibc 2.1 you need version 0.36. The apps should
installed into /usr/inet6.
The apps are available on ftp.inner.net or on its mirrors, e.g.
<URL:ftp://6bone.informatik.uni-leipzig.de/pub/ftp.inner.net/pub/ipv6/inet6-apps-0.35.tar.gz>
resp.
<URL:ftp://6bone.informatik.uni-leipzig.de/pub/ftp.inner.net/pub/ipv6/inet6-apps0.36.tar.gz>
Furthermore you need a connection to the 6bone
(<URL:http://www.join.uni-muenster.de/>).
Newer versions of AIX also come with IPv6 support.
mySQL
-----
If your machine has mySQL installed, the driver can be configured to use
it: give '--enable-use-mysql=yes' as argument to the configure script.
Alternatively, if your mySQL uses an unusual include/library path,
the option can be given as '--enable-use-mysql=/unusual/path', which
will use the given path as search path for both include and library
files in addition to the normal system search paths. The include files will
be searched in <path>/include and <path>, the library files will be search
in <path>/lib/mysql, <path>/lib, and <path>, in this order.
The username and password for the mySQL database are specified by
the mudlib as arguments to the efun db_connect().
Use mysqladmin to create any databases you want to provide - the
names are later used in the efun db_connect() to connect to
the databases.
BeOS
----
Under BeOS, the driver can be configured and compiled in two ways:
1. Using the provided configuration files.
Copy the files machine.h, config.h and Makefile from src/hosts/be/
to src/. You may have to edit config.h and Makefile if you have
to use a specific mudlib with exotic settings.
Advantage of this method is that the Makefile allows cross-compilation
and covers Be specifics like file icon, type and version.
2. Use the Unix configure mechanism.
In general just follow the instructions given for Unix systems, but
be aware of the follwing:
- If the configure script doesn't properly work, try starting it
with
CC="$BE_C_COMPILER" EXTRA_CFLAGS="$BE_DEFAULT_C_FLAGS" ./configure
or (especially on BeOS R4.5 on PPC) even
CC=cc EXTRA_CFLAGS="$BE_DEFAULT_C_FLAGS" ./configure
- the created executable will have neither icon nor type.
- cross compilation is not supported.
- the Makefile defaults to best optimization which needs a lot
of memory during compilation.
If on driver start you get an error about an unknown hostname or
seems to hang, you're missing an /etc/hosts file:
- In the network preferences, select a name for you machine,
e.g. 'bebox'. The domain name field can be blank.
- Copy the /boot/beos/etc/hosts-sample file to /boot/beos/etc/hosts,
and edit it to contain at least the following lines:
127.0.0.1 bebox.my-isp.com bebox
127.1 bebox.my-isp.com bebox
(Note: in the file, every line has to start with the IP address -
no leading spaces are allowed).
With the current networking implementation, the driver is unable
to start ERQs. In order to use ERQs, you have to start them manually.
Other than this, the installation steps are the same as for Unix.
Windows 95/98/NT
----------------
To compile the gamedriver for Windows, you need the 'Cygwin' package,
which is a port of gcc, bash, and other GNU/Unix programs. Once it
is installed and running, the procedure is the same as under Unix.
CygWin is available from <URL:http://www.cygwin.com/> or
<http://www.redhat.com/software/cygwin/>, and when installing make sure that
your installation includes gcc, bash, make, sed, awk, and bison.
One common pitfall is if the installation does not create the '/bin'
directory in which the CygWin executables are expected. A typical
error message would be 'make: /bin/sh not found'.
Solution 1: Create a directory 'bin' in your search path (e.g. c:\bin)
and copy all required executables (in this case 'sh.exe') into
that directory.
Solution 2 (this can be done in a script): cd into the directory
where the executables are stored, e.g.
/compiler/Cygnus/B19/H-i386-cygwin32/bin . In this directory, give
the command 'mount $PWD /bin'.
Solution 3: Use a newer version of Cygwin where this problem apparently
has been solved.
A driver compiled by David Gibbs (ishara@btinternet.com) is available
at <URL:http://www.einy.freeserve.co.uk/lpmud.index.html>.
The following comments were provided by Robert Nurrie(?) who had
an misconfigured Cygnus installation (Summer 2000):
"Make sure you've used the setup.exe you get when clicking the 'install
cygwin now' link in the upper right corner of their website, instead of
the setup.exe found on the ftp-site.
Oh, and when you're given the choice of default text file type you
should of course chose Dos, as that seems to be the key."
Brandon Mathis points out, "that to compile under Windows you have to
use 'tar -xvfj' and not WinZIP to extract the source".
OS/2
----
The OS/2 port uses the EMX (a gcc version) to compile the gamedriver.
To compile the driver, copy the machine.h and Makefile from the hosts/os2
directory into the top directory and make as under Unix. The Makefile
is configured to install the driver in /mud - edit the variable 'prefix'
if you want a different directory.
Important: the Makefile must be save using the Unix lineend convention,
otherwise the make program will stop with an error. In the EPM editor
this can be achieved using the 'save -u' command.
If you have the full GNU suite installed, you can also configure the
driver as under Unix. Following caveats regarding the configure script:
- the ac_exeext variable may not be set to '.exe' as it should be;
- the calls to the program conftest may lack the ${ac_exeext} extension.
Additionally, configure does not properly recognize the settings for
HAVE_GETRUSAGE, GETRUSAGE_RESTRICTED, GETRUSAGE_VIA_SYSCALL and RUSAGE_USEC.
Copy these values from the provided machine.h
To recreate the configure script from configure.in, you need autoconf
version 2.50 or newer.

26
README Normal file
View File

@ -0,0 +1,26 @@
The files in this directory are:
HELP : basics, serves also as source for the man file.
README : this file.
COPYRIGHT : the copyright of the driver.
CREDITS : the list of contributors.
HISTORY (removed)
CHANGELOG : the last changes in minute detail.
COPYING.LIB : the GNU Library Public License.
INSTALL : installation hints and notes.
FAQ : unfrequently answered questions.
psyclpc.1 : manual file.
doc/ (removed) the documentation is available on the web or
in the LDMud distribution.
src/ : the driver source
pkg/ : additional packages (unsupported and supported) for the driver.
mudlib/ : various LPC (example) files.
mudlib/sys/:
standard include files to copy into your mudlib. Some of these are
also used by the src/ files.
mud/ (removed) the lp-245 mudlib, and support files for other mudlibs.
Nice! Somebody made a doxygen of ldmud and posted it on
http://lpmuds.net/ldmud/dox/dir_2cb66bf95229e25b825da12cd79535c5.html

90
TODO Normal file
View File

@ -0,0 +1,90 @@
FROM LDMUD
+ we are glad to find out that Lars is back and working on ldmud! :D
- examine & apply: 2320, 2334, 2335, 2336, 2340, 2341
BUGS
- #define USE_EXPAT und JSON werden trotzdem gesetzt in config.h
auch wenn configure keine libs gefunden hat (egal, wir verwenden beide nicht)
- Because of some funny bug the driver will probably not bind properly
to _basic_host_IP as it also needs _basic_host_name and _basic_host_domain
to be provided. Hopefully this shortcoming will soon be history.
WINDOWS SUPPORT
+ with the new __NO_SRV__ detection psyclpc compiles under cygwin but it
doesn't provide SRV which makes it a suboptimal XMPP router.. just in
case you want that.
fippo suggests to put http://delta.affinix.com/jdns/ into psyclpc
http://www.chiark.greenend.org.uk/~ian/adns/ requires a locally running
nameserver.. and i don't think it even runs on cygwin.. other ideas?
COMPLAINTS
-* QA Notice: Package has poor programming practices which may compile
* fine but exhibit random runtime failures.
* interpret.c:7224: warning: dereferencing type-punned pointer will break strict-aliasing rules
MISC IDEAS
- make more MUD features optional: more d_flag stuff?
? USE_RESETS time_of_ref USE_CLEANUP load_id USE_WIZLIST USE_EXPAT USE_EVALUATION_COST
- disabling with_input_escape does not disable the input_escape handling source code
+ teach ldmud to exec() so that, together with --args, we can run it as a
regular daemon without kludgy shellscripts
(http://mantis.bearnip.com/view.php?id=55)
+ provide a query_shutdown_progress() efun to inform about progress
and the intention to either shutdown or restart. maybe even a reason?
+ optimize f_lower_case by adding an 'already lowercase' flag to the
string data structure
+ ldap package erproben und fertigmachen
+ put errno() back in
+ psyctext() in C ... see psyced/CHANGESTODO for details
? bugless says there is an ioctl() to obtain a descriptor's owner uid
thus avoid the authlocal /proc hack
? have a seperate package for the LPC documentation and update it a bit
since ldmud?
+ fip thinks we should have a new operator with arguments rather than
clone_object and subsequent -> calls. pike doesn't even have the "new"
because unlike C++ and LPC it forbids static use of classes (aka "blueprints")
+ fippo suggests to look into http://www.hpl.hp.com/personal/Hans_Boehm/gc/leak.html
+ DMSG_FLUSH for incremental debug messages :)
- for pike compatibility allow string[-1] just like string[<1]
ENCRYPTION (see http://about.psyc.eu/Talk:Encryption)
? link libpurple to this for protocol supports and OTR hahahahaha
? or link libotr only?
? or is OTR too expensive anyway and we should try SS-TLS?
USE_RESTORED_OBJECTS
+ object names need to be able to be identical to uniforms
then it doesn't matter if they came back from persistence as strings
as sendmsg() can handle both objects and uniforms - we just need to
deal with mappings where both the object and the uniform could be the key..
(members & routes of places)
NETWORKING
- http://mantis.bearnip.com/view.php?id=442 (MAX_TEXT)
- add_message("%s", "\n*** Text lost in transmission ***\n");
should be passed to master instead.
+ _length: <eL> somebody implement a new input_to(#'get_data, length).
? MAYBE the whole networking should be replaced by libevent!??
+ support epoll() / kqueue (or just libevent?)
? allow port definition from lpc:master.c or even dynamic listen()
so we can add port config to the web configurator
..egal, machen wir jetzt über psyconf
CHARSET
-? keeping track of charset everywhere to avoid any unnecessary conversion
would lead to so much overhead, that occasional unnecessary conversion is
the cheaper option. that's why we should convert in the driver close to
the network operations:
comm.c:3055: if(ip->tls_inited)
l = tls_read(ip, ip->text + ip->text_end, (size_t)l);
else if (!(ip->tls_want))
l = socket_read(ip->socket, ip->text + ip->text_end, ...
+ since network read operations are much more efficient than input_to-lines
iconv charset conversions should happen right after socket/tls_read()
into a pre-buffer, then copy-converted into the interactive's buffer
+ outgoing transmissions need to find the same treatment, before
socket_write() and also before optional compression.
+ socket charset is stored in interactive_s and given by an efun
+ charset is compared to SYSTEM_CHARSET which is given by config.h/configure
- http://mantis.bearnip.com/view.php?id=117

14
etc/README Normal file
View File

@ -0,0 +1,14 @@
Miscellaneous files for the driver:
lpc-mode.el : LPC mode for EMACS, by Vivek Dasmohapatra <vivek@etla.org>
lpc.xml : LPC syntax highlighting for Kate, by <Andreas.Klauer@epost.de>
lpc.vim : LPC syntax highlighting for vim, maintained by Shizhu
Pan <poet@mudbuilder.net>
savefile-parse.pl: A perl snippet which reads a LPMud savefile and
transforms it into a Perl datastructure.
The following scripts are just working examples - use them to roll your own:
memusage : A script to analyze OBJ_DUMP.

382
etc/lpc-mode.el Normal file
View File

@ -0,0 +1,382 @@
;; LPC mode
;;
;; Emacs Lisp Archive Entry
;; Package: lpc-mode
;; Filename: lpc-mode.el
;; Version: 0.12
;; Keywords: languages, LPC
;; Author: Vivek Dasmohapatra <vivek@etla.org>
;; Maintainer: Vivek Dasmohapatra <vivek@etla.org>
;; Created: 2002-08-31
;; Description: syntax highlighting/indentation for LPC
;; URL: http://rtfm.etla.org/emacs/lpc-mode/
;; Compatibility: Emacs21
;; Last-Updated: Tue 2002-09-17 23:59:51 +0100
;; This file is NOT part of GNU Emacs
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
;; Copyright (C) 2002 Vivek Dasmohapatra <vivek@etla.org>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2 of the License, or
;; (at your option) any later version.
;; OK Nick: first stab at LPC mode:
;; 0.01: 'foo and 'C' should be handled correctly.
;; 0.02 ... 0.06: intermediates.
;; 0.07: ultra-hairy ({#'[][,&] syntax now scanned for. Bleurgh.
;; 0.08: ({ ... }) syntax added as brace-list
;; 0.09: rip up and rewrite as a proper cc-mode based mode
;; 0.10: miscellaneous bugfixes.
;; 0.11: should compile cleanly now _and_ work as well (I hope)
;; 0.12: bug in `lpc-font-lock-map' keyword/function definition highlighting
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; HOW TO INSTALL:
;;
;; ;; either put lpc-mode.el in your load path and use:
;; (autoload 'lpc-mode "lpc-mode" t)
;;
;; ;; or have:
;; (autoload 'lpc-mode "/path/to/lpc-mode.el" t)
;;
;; ;; then:
;; (setq auto-mode-alist
;; (append '(("\\.lpc$" . lpc-mode)) auto-mode-alist)) )
;;
;; Nick: You'll have to do similar things to handler.el to get that to
;; work, let me know if you need this done.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; elisp-dep-block >>
(require 'custom );(defface)
(require 'cc-mode );(c-electric-brace)
(require 'regexp-opt);(regexp-opt-depth regexp-opt)
(require 'font-lock )
;;(font-lock-add-keywords font-lock-fontify-region font-lock-mode)
;; elisp-dep-block <<
(defconst lpc-mode-version "0.12")
(eval-and-compile
(defmacro lpc-defsyntax (name doc klist)
"Declare a cc-mode syntax variable of lpc-N-keywords and a regex
lpc-N-regex to go along with it, based on the keyword list K."
(let* ((n name )
(d doc )
(k klist)
(ln (format "lpc-%s-keywords" n))
(ld (format "%s (list)" d))
(ls (intern ln))
(rn (format "lpc-%s-regex" n))
(rd (format "%s (regex)" d))
(rs (intern rn))
(kwds nil))
(setq kwds (if (stringp (car k)) k (eval k)))
;;(message "%s" (format "%S" kwds))
`(progn (defconst ,ls ',kwds ,ld)
(defconst ,rs (regexp-opt ',kwds) ,rd)) ))
(lpc-defsyntax type
"LPC primitive type keywords."
("int" "mapping" "mixed" "object" "status" "string" "void"))
(lpc-defsyntax specifier
"LPC declaration specifier keywords."
("nomask" "private" "public" "static" "varargs"))
(lpc-defsyntax other-decl
"LPC keywords starting other decl-level constructs."
("inherit"))
(lpc-defsyntax block-stmt-1
"LPC keywords followed directly by a block."
("do" "else"))
(lpc-defsyntax block-stmt-2
"LPC keywords followed by a paren sexp and then by a block."
("for" "if" "switch" "while" "foreach"))
(lpc-defsyntax simple-stmt
"LPC statement keywords followed by an expression or nothing."
("break" "continue" "return"))
(lpc-defsyntax label
"LPC keywords introducing labels in blocks."
("case" "default"))
(lpc-defsyntax all
"LPC keywords."
(append lpc-type-keywords
lpc-specifier-keywords
lpc-other-decl-keywords
lpc-block-stmt-1-keywords
lpc-block-stmt-2-keywords
lpc-simple-stmt-keywords
lpc-label-keywords ))
(lpc-defsyntax default-highlight
"LPC keywords (for default highlighting)"
(append lpc-specifier-keywords
lpc-block-stmt-1-keywords
lpc-block-stmt-2-keywords
lpc-simple-stmt-keywords ))
(lpc-defsyntax conditional
"LPC conditional keywords"
(append lpc-block-stmt-1-keywords lpc-block-stmt-2-keywords))
)
(defconst lpc-comment-start-regex c-C++-comment-start-regexp)
(defconst lpc-special-brace-lists '((?{ . ?})) )
(defconst lpc-magic-quote-comma '(9))
(defconst lpc-magic-symbol-name '(3))
(defvar lpc-mode-syntax-table nil)
(if lpc-mode-syntax-table
nil
(setq lpc-mode-syntax-table (make-syntax-table))
(c-populate-syntax-table lpc-mode-syntax-table)
(modify-syntax-entry ?\' "'" lpc-mode-syntax-table) )
(defun lpc-modify-syntax-at (beg end syntax)
"Apply a syntax-property value syntax from beg to end."
(if (<= (point-max) end) nil; noop
(progn
;;(message "(%d x %d) => %S" beg end syntax)
(put-text-property beg end 'syntax-table syntax)
(put-text-property (1- end) end 'rear-nonsticky t ))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Code by Seth Golub <seth AT cs DOT wustl DOT edu>, 1996-02-01,
;; no licence.
;;
;; modified slightly to bring this up to date, didn't work quite right
;; out of the box:
(defun lpc-maybe-electric-brace (arg)
"Insert character and maybe correct line's indentation."
(interactive "P")
(if (= last-command-char ?{)
(if (= (preceding-char) ?\()
(self-insert-command (prefix-numeric-value arg))
(c-electric-brace arg))
;; (= last-command-char ?})
(let (start-point state containing-sexp)
(save-excursion (beginning-of-defun)
(setq start-point (point)))
(save-excursion (setq state (parse-partial-sexp (point) start-point 0)))
(setq containing-sexp (car (cdr state)))
(if (and containing-sexp (save-excursion
(goto-char (1- containing-sexp))
(looking-at "(")))
(progn
(self-insert-command (prefix-numeric-value arg))
(lpc-scan-magic-quote))
(c-electric-brace arg)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defconst lpc-magic-quote-regex "({\\s-*#'\\([^\\s-\n,}]+\\|,\\)\\s-*[,}]")
(defun lpc-magic-comma-p (pt)
(let ((bol nil) (eol nil) (pos nil) (ret nil))
(save-excursion
(goto-char pt)
(end-of-line)
(setq eol (point))
(beginning-of-line)
(setq bol (point))
(while (and (not ret)
(setq pos (re-search-forward lpc-magic-quote-regex eol t)))
;;(message "magic pattern at %d/%d" (1- pos) pt)
(if (/= (1- pos) pt) nil
(setq ret (list (- (match-beginning 1) 1)
(match-beginning 1)
(match-end 1)
bol)) ) )) ret))
(defun lpc-scan-magic-quotes ()
(save-excursion
(let ((qpos nil) (wbeg nil) (wend nil))
(while (re-search-forward lpc-magic-quote-regex nil t)
(setq qpos (+ (match-beginning 0) 3)
wbeg (match-beginning 1)
wend (match-end 1))
(lpc-modify-syntax-at qpos (1+ qpos) lpc-magic-quote-comma)
(lpc-modify-syntax-at wbeg wend lpc-magic-symbol-name)
)
)
)
)
(defun lpc-scan-magic-quote ()
(save-excursion
(let ((coord nil) (qpos nil) (wbeg nil) (wend nil) (bol nil))
(if (setq coord (lpc-magic-comma-p (1- (point))))
(progn
(setq qpos (car coord)
wbeg (cadr coord)
wend (car (cddr coord))
bol (cadr (cddr coord)))
;;(message "magic pattern at (%d %d %d)" qpos wbeg wend)
(lpc-modify-syntax-at qpos (1+ qpos) lpc-magic-quote-comma)
(lpc-modify-syntax-at wbeg wend lpc-magic-symbol-name)
(font-lock-fontify-region bol wend) )
)
)
)
)
(defun lpc-maybe-quote-ref (arg)
"Kludge to work around multiple syntactic meanings of `,' `[' et al in LPC."
(interactive "P")
(self-insert-command (prefix-numeric-value arg))
(lpc-scan-magic-quote) )
(defvar lpc-mode-map nil "Keymap for LPC mode buffers.")
(if lpc-mode-map
nil
(setq lpc-mode-map (c-make-inherited-keymap))
(define-key lpc-mode-map "\C-c:" 'c-scope-operator)
(define-key lpc-mode-map "{" 'lpc-maybe-electric-brace)
(define-key lpc-mode-map "}" 'lpc-maybe-electric-brace)
(define-key lpc-mode-map "," 'lpc-maybe-quote-ref)
(define-key lpc-mode-map "\C-c\C-e" 'c-macro-expand)
)
(defvar lpc-mode-hook nil)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; font-lock support:
(defvar lpc-reference-face 'lpc-reference-face)
(defface lpc-reference-face
'((((class color) (background dark)) (:foreground "bisque" ))
(((class color) (background light)) (:foreground "dark blue")))
"LPC mode face for quoted symbols")
(defconst lpc-type-depth (regexp-opt-depth lpc-type-regex))
(defconst lpc-font-lock-map
(append
c-font-lock-keywords-1
(list
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; what follows is mostly ripped from font-lock.el, mostly...
`(eval . (cons (concat "\\<\\(" ,lpc-type-regex "\\)\\>")
'font-lock-type-face))
(concat "\\<\\(" lpc-default-highlight-regex "\\)\\>")
'("\\<\\(case\\)\\>" (1 font-lock-keyword-face)
("\\(-[0-9]+\\|\\sw+\\)"
;; Return limit of search.
(save-excursion (skip-chars-forward "^:\n") (point))
nil
(1 font-lock-constant-face nil t)))
'(":" ("^[ \t]*\\(\\sw+\\)[ \t]*:[ \t]*$"
(beginning-of-line) (end-of-line)
(1 font-lock-constant-face)))
`(eval . (list
(concat "\\<\\(" ,lpc-type-regex "\\)\\>"
"\\([ \t*&]+\\sw+\\>\\)*")
;; Fontify each declaration item.
(list
'font-lock-match-c-style-declaration-item-and-skip-to-next
;; Start with point after all type specifiers.
(list 'goto-char
(list 'or
(list 'match-beginning
(+ ,lpc-type-depth 2))
'(match-end 1)))
;; Finish with point after first type specifier.
'(goto-char (match-end 1))
;; Fontify as a variable or function name.
'(1 (if (match-beginning 2)
font-lock-function-name-face
font-lock-variable-name-face)))))
;; Fontify anything at beginning of line as a declaration or definition.
'("^\\(\\sw+\\)\\>\\([ \t*]+\\sw+\\>\\)*"
(1 font-lock-type-face)
(font-lock-match-c-style-declaration-item-and-skip-to-next
(goto-char (or (match-beginning 2) (match-end 1))) nil
(1 (if (match-beginning 2)
font-lock-function-name-face
font-lock-variable-name-face))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; and now native LPC highlighting:
'("\\('.'\\|'\\\\.'\\)" 1 font-lock-string-face keep)
;; lambda thingies
'("{\\s-*\\(#\\)" 1 font-lock-builtin-face keep)
'("'\\([^}, \t;]+\\)" 1 lpc-reference-face keep)
'("'\\(,\\)[,} \t\n]" 1 lpc-reference-face keep)
;;
'("\\(\\binherit\\)\\s-+\\s\".+\";" 1 font-lock-builtin-face t)
)
)
)
(defun lpc-set-font-lock-defaults ()
"Set up LPC mode font-lock stuff."
(let ((font-lock-defaults '(lpc-font-lock-map
nil
nil
((?_ . "w") (?\' . "'"))
beginning-of-defun
(font-lock-mark-block-function . mark-defun))))
(font-lock-set-defaults)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; bring it all together:
(defun lpc-mode ()
(interactive)
(c-initialize-cc-mode)
(kill-all-local-variables)
(set-syntax-table lpc-mode-syntax-table)
(make-variable-buffer-local 'parse-sexp-lookup-properties)
(set 'parse-sexp-lookup-properties t)
(setq major-mode 'lpc-mode
mode-name "LPC")
(use-local-map lpc-mode-map)
(c-common-init)
(setq c-keywords (c-identifier-re lpc-all-regex)
c-special-brace-lists lpc-special-brace-lists
comment-start "// "
comment-end ""
c-conditional-key lpc-conditional-regex
c-comment-start-regexp lpc-comment-start-regex
c-extra-toplevel-key lpc-other-decl-regex
;; c-class-key nil ;; cannot set this to nil or ""
c-method-key nil
c-baseclass-key nil
c-recognize-knr-p nil
c-lambda-key nil
c-inexpr-block-key nil
c-inexpr-class-key nil)
(lpc-set-font-lock-defaults)
(lpc-scan-magic-quotes)
(if (not noninteractive)
(turn-on-font-lock)
(let ((font-lock-mode t) (noninteractive nil))
(turn-on-font-lock)))
(run-hooks 'c-mode-common-hook)
(run-hooks 'lpc-mode-hook)
(c-update-modeline)
)
(provide 'lpc-mode)
;; lpc-mode.el ends here

447
etc/lpc.vim Normal file
View File

@ -0,0 +1,447 @@
" Vim syntax file
" Language: LPC
" Maintainer: Shizhu Pan <poet@mudbuilder.net>
" URL: http://poet.tomud.com/pub/lpc.vim.bz2
" Last Change: 2003 May 11
" Comments: If you are using Vim 6.2 or later, see :h lpc.vim for
" file type recognizing, if not, you had to use modeline.
" Changed for LDMud 3.2 and 3.3, Coogan@Tubmud, 02-Sep-2003
" Nodule: This is the start nodule. {{{1
" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
" Nodule: Keywords {{{1
" LPC keywords
" keywords should always be highlighted so "contained" is not used.
syn cluster lpcKeywdGrp contains=lpcConditional,lpcLabel,lpcOperator,lpcRepeat,lpcStatement,lpcModifier,lpcReserved
syn keyword lpcConditional if else switch
syn keyword lpcLabel case default
syn keyword lpcOperator catch efun in inherit nolog publish
syn keyword lpcRepeat do for foreach while
syn keyword lpcStatement break continue return function
syn match lpcEfunError /efun[^:]/ display
" Illegal to use keyword as function
" It's not working, maybe in the next version.
syn keyword lpcKeywdError contained if for foreach return switch while
" These are keywords only because they take lvalue or type as parameter,
" so these keywords should only be used as function but cannot be names of
" user-defined functions.
" syn keyword lpcKeywdFunc new parse_command sscanf time_expression
" Nodule: Type and modifiers {{{1
" Type names list.
" Special types
syn keyword lpcType void mixed unknown
" Scalar/Value types.
syn keyword lpcType int float string status
" Pointer types.
syn keyword lpcType array function mapping object struct
" Other types.
syn keyword lpcType closure funcall
" Type modifier.
syn keyword lpcModifier nomask private public
syn keyword lpcModifier varargs virtual
" sensible modifiers
syn keyword lpcModifier nosave protected static
" Nodule: Applies {{{1
" Match a function declaration or function pointer
syn match lpcApplyDecl excludenl /->\h\w*(/me=e-1 contains=lpcApplies transparent display
" We should note that in func_spec.c the efun definition syntax is so
" complicated that I use such a long regular expression to describe.
syn match lpcLongDecl excludenl /\(\s\|\*\)\h\+\s\h\+(/me=e-1 contains=@lpcEfunGroup,lpcType,@lpcKeywdGrp transparent display
" this is form for all functions
" ->foo() form had been excluded
syn match lpcFuncDecl excludenl /\h\w*(/me=e-1 contains=lpcApplies,@lpcEfunGroup,lpcKeywdError transparent display
" The (: :) parenthesis or $() forms a function pointer
syn match lpcFuncName /(:\s*\h\+\s*:)/me=e-1 contains=lpcApplies,@lpcEfunGroup transparent display contained
syn match lpcFuncName /(:\s*\h\+,/ contains=lpcApplies,@lpcEfunGroup transparent display contained
syn match lpcFuncName /\$(\h\+)/ contains=lpcApplies,@lpcEfunGroup transparent display contained
" Applies list.
" system applies for compat mode
syn keyword lpcApplies contained add_weight can_put_and_get drop get prevent_insert query_weight
" system applies for native mode
syn keyword lpcApplies contained create
" system applies
syn keyword lpcApplies contained __INIT catch_msg clean_up exit heart_beat id init reset
" interactive
syn keyword lpcApplies contained catch_tell logon modify_command
" master applies
syn keyword lpcApplies contained compile_object connect creator_file dangling_lfun_closure disconnect epilog external_master_reload flag get_bb_uid get_ed_buffer_save_file_name get_master_uid get_simul_efun get_wiz_name heart_beat_error inaugurate_master include_file inherit_file log_error make_path_absolute notify_shutdown preload prepare_destruct printf_obj_name privilege_violation query_allow_shadow quota_demon reactivate_destructed_master receive_imp receive_udp remove_player retrieve_ed_setup runtime_error save_ed_setup slow_shutdown stale_erq
syn keyword lpcApplies contained valid_exec valid_query_snoop valid_read valid_seteuid valid_snoop valid_trace valid_write
" parsing
syn keyword lpcApplies contained parse_command_adjectiv_id_list parse_command_all_word parse_command_id_list parse_command_plural_id_list parse_command_prepos_list
" Nodule: Efuns {{{1
syn cluster lpcEfunGroup contains=lpc_efuns,lpcOldEfuns,lpcNewEfuns,lpcKeywdFunc,lpcCompatEfuns,lpcNativeEfuns,lpcSimulEfuns
" syn match lpcErrFunc /#`\h\w*/
" Shell compatible first line comment.
" syn region lpcCommentFunc start=/^#!/ end=/$/
" efuns which are [to be] removed in newer versions of LDMud.
syn keyword lpcOldEfuns contained add_verb add_xverb allocate_mapping copy_mapping efun308 file_name filter_array filter_mapping m_sizeof map_array map_mapping mapping_contains member_array parse_command query_imp_port send_imp set_auto_include_string transfer
" new efuns of LDMud 3.3
syn keyword lpcNewEfuns contained baseof call_direct call_direct_resolved match_command md5_crypt regmatch
syn keyword lpcNewEfuns contained start_mccp_compress end_mccp_compress query_mccp query_mccp_stats
syn keyword lpcNewEfuns contained pg_connect pg_query pg_pending pg_close
syn keyword lpcNewEfuns contained struct_info structp to_struct
syn keyword lpcNewEfuns contained tls_query_connection_state tls_query_connection_info tls_init_connection tls_deinit_connection tls_error
syn keyword lpcCompatEfuns contained creator
syn keyword lpcNativeEfuns contained export_uid geteuid getuid seteuid
" simul efuns, add your simul efuns here
syn keyword lpcSimulEfuns contained transfer
" LPC efuns list.
" Efuns list {{{2
syn keyword lpc_efuns contained abs acos add_action all_environment all_inventory allocate allocate_mapping and_bits apply asin assoc atan atan2 attach_erq_demon
syn keyword lpc_efuns contained binary_message bind_lambda blueprint break_point
syn keyword lpc_efuns contained call_other call_out call_out_info call_resolved caller_stack caller_stack_depth capitalize cat catch ceil clear_bit clone_object clonep clones closurep command command_stack command_stack_depth copy copy_bits copy_file cos count_bits crypt ctime
syn keyword lpc_efuns contained db_affected_rows db_close db_coldefs db_connect db_conv_string db_error db_exec db_fetch db_handles db_insert_id debug_info debug_message deep_copy deep_inventory destruct disable_commands
syn keyword lpc_efuns contained ed enable_commands environment exec execute_command exp expand_define explode extern_call extract
syn keyword lpc_efuns contained file_size filter filter_indices filter_objects find_call_out find_input_to find_object first_inventory floatp floor funcall function_exists functionlist
syn keyword lpc_efuns contained garbage_collection get_dir get_error_file get_eval_cost get_extra_wizinfo get_type_info gmtime
syn keyword lpc_efuns contained heart_beat_info
syn keyword lpc_efuns contained implode include_list inherit_list input_to input_to_info insert_alist interactive intersect_alist intp invert_bits
syn keyword lpc_efuns contained lambda last_bit last_instructions limited living load_name load_object localtime log lower_case
syn keyword lpc_efuns contained m_add m_allocate m_contains m_delete m_entry m_indices m_reallocate m_values make_shared_string map map_indices map_objects mappingp max md5 member min mkdir mkmapping move_object
syn keyword lpc_efuns contained negate next_bit next_inventory notify_fail
syn keyword lpc_efuns contained object_info object_name object_time objectp or_bits order_alist
syn keyword lpc_efuns contained pointerp pow present present_clone previous_object printf process_string program_name program_time
syn keyword lpc_efuns contained query_actions query_command query_editing query_idle query_input_pending query_ip_name query_ip_number query_limits query_load_average query_mud_port query_notify_fail query_once_interactive query_shadowing query_snoop query_udp_port query_verb quote
syn keyword lpc_efuns contained raise_error random read_bytes read_file referencep regexp regexplode regmatch regreplace remove_action remove_call_out remove_input_to remove_interactive rename rename_object replace_program restore_object restore_value rm rmdir rmember rusage
syn keyword lpc_efuns contained save_object save_value say send_erq send_udp set_bit set_buffer_size set_combine_charset set_connection_charset set_driver_hook set_environment set_extra_wizinfo set_extra_wizinfo_size set_heart_beat set_is_wizard set_light set_limits set_modify_command set_next_reset set_prompt set_this_object set_this_player sgn shadow shutdown sin sizeof slice_array snoop sort_array sprintf sqrt sscanf stringp strlen strrstr strstr swap symbol_function symbol_variable symbolp
syn keyword lpc_efuns contained tail tan tell_object tell_room terminal_colour test_bit this_interactive this_object this_player throw time to_array to_float to_int to_object to_string trace traceprefix transpose_array trim typeof
syn keyword lpc_efuns contained unbound_lambda unique_array unmkmapping unquote unshadow upper_case users utime
syn keyword lpc_efuns contained variable_exists variable_list
syn keyword lpc_efuns contained walk_mapping widthof wizlist_info write write_bytes write_file
syn keyword lpc_efuns contained xor_bits
" Nodule: Constants {{{1
" LPC Constants.
" like keywords, constants are always highlighted, be careful to choose only
" the constants we used to add to this list.
syn keyword lpcConstant LPC3 __LDMUD__ __EUIDS__ COMPAT_FLAG __COMPAT_MODE__ __STRICT_EUIDS__ __FILENAME_SPACES__ __MASTER_OBJECT__ __FILE__ __LINE__ __DIR__ __PATH__ __VERSION__ __VERSION_MAJOR__ __VERSION_MINOR__ __VERSION_MICRO__ __VERSION_PATCH__ __DOMAIN_NAME__ __HOST_IP_NUMBER__ __HOST_NAME__ __MAX_RECURSION__ __MAX_EVAL_COST__ __CATCH_EVAL_COST__ __MASTER_EVAL_COST__ __RESET_TIME__ __CLEANUP_TIME__ __EFUN_DEFINED__ __DRIVER_LOG__ __WIZLIST__ __INT_MAX__ __INT_MIN__ __FLOAT_MAX__ __FLOAT_MIN__ __MAX_MALLOC__
" Nodule: Todo for this file. {{{1
" TODO : need to check for LPC4 syntax and other series of LPC besides
" v22, b21 and l32, if you had a good idea, contact me at poet@mudbuilder.net
" and I will be appreciated about that.
" Notes about some FAQ:
"
" About variables : We adopts the same behavior for C because almost all the
" LPC programmers are also C programmers, so we don't need separate settings
" for C and LPC. That is the reason why I don't change variables like
" "c_no_utf"s to "lpc_no_utf"s.
"
" Copy : Some of the following seems to be copied from c.vim but not quite
" the same in details because the syntax for C and LPC is different.
"
" Color scheme : this syntax file had been thouroughly tested to work well
" for all of the dark-backgrounded color schemes Vim has provided officially,
" and it should be quite Ok for all of the bright-backgrounded color schemes,
" of course it works best for the color scheme that I am using, download it
" from http://poet.tomud.com/pub/ps_color.vim.bz2 if you want to try it.
"
" Nodule: String and Character {{{1
" String and Character constants
" Highlight special characters (those which have a backslash) differently
syn match lpcSpecial display contained "\\\(x\x\+\|\o\{1,3}\|.\|$\)"
if !exists("c_no_utf")
syn match lpcSpecial display contained "\\\(u\x\{4}\|U\x\{8}\)"
endif
" LPC version of sprintf() format,
syn match lpcFormat display "%\(\d\+\)\=[-+ |=#@:.]*\(\d\+\)\=\('\I\+'\|'\I*\\'\I*'\)\=[OsdicoxXf]" contained
syn match lpcFormat display "%%" contained
syn region lpcString start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=lpcSpecial,lpcFormat
" lpcCppString: same as lpcString, but ends at end of line
syn region lpcCppString start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=lpcSpecial,lpcFormat
" LPC preprocessor for the text formatting short cuts
" Thanks to Dr. Charles E. Campbell <cec@gryphon.gsfc.nasa.gov>
" he suggests the best way to do this.
syn region lpcTextString start=/@\z(\h\w*\)$/ end=/^\z1/ contains=lpcSpecial
syn region lpcArrayString start=/@@\z(\h\w*\)$/ end=/^\z1/ contains=lpcSpecial
" Character
syn match lpcCharacter "L\='[^\\]'"
syn match lpcCharacter "L'[^']*'" contains=lpcSpecial
syn match lpcSpecialError "L\='\\[^'\"?\\abefnrtv]'"
syn match lpcSpecialCharacter "L\='\\['\"?\\abefnrtv]'"
syn match lpcSpecialCharacter display "L\='\\\o\{1,3}'"
syn match lpcSpecialCharacter display "'\\x\x\{1,2}'"
syn match lpcSpecialCharacter display "L'\\x\x\+'"
" Nodule: White space {{{1
" when wanted, highlight trailing white space
if exists("c_space_errors")
if !exists("c_no_trail_space_error")
syn match lpcSpaceError display excludenl "\s\+$"
endif
if !exists("c_no_tab_space_error")
syn match lpcSpaceError display " \+\t"me=e-1
endif
endif
" Nodule: Parenthesis and brackets {{{1
" catch errors caused by wrong parenthesis and brackets
syn cluster lpcParenGroup contains=lpcParenError,lpcIncluded,lpcSpecial,lpcCommentSkip,lpcCommentString,lpcComment2String,@lpcCommentGroup,lpcCommentStartError,lpcUserCont,lpcUserLabel,lpcBitField,lpcCommentSkip,lpcOctalZero,lpcCppOut,lpcCppOut2,lpcCppSkip,lpcFormat,lpcNumber,lpcFloat,lpcOctal,lpcOctalError,lpcNumbersCom
syn region lpcParen transparent start='(' end=')' contains=ALLBUT,@lpcParenGroup,lpcCppParen,lpcErrInBracket,lpcCppBracket,lpcCppString,@lpcEfunGroup,lpcApplies,lpcKeywdError
" lpcCppParen: same as lpcParen but ends at end-of-line; used in lpcDefine
syn region lpcCppParen transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@lpcParenGroup,lpcErrInBracket,lpcParen,lpcBracket,lpcString,@lpcEfunGroup,lpcApplies,lpcKeywdError
syn match lpcParenError display ")"
syn match lpcParenError display "\]"
" for LPC:
" Here we should consider the array ({ }) parenthesis and mapping ([ ])
" parenthesis and multiset (< >) parenthesis.
syn match lpcErrInParen display contained "[^^]{"ms=s+1
syn match lpcErrInParen display contained "\(}\|\]\)[^)]"me=e-1
syn region lpcBracket transparent start='\[' end=']' contains=ALLBUT,@lpcParenGroup,lpcErrInParen,lpcCppParen,lpcCppBracket,lpcCppString,@lpcEfunGroup,lpcApplies,lpcFuncName,lpcKeywdError
" lpcCppBracket: same as lpcParen but ends at end-of-line; used in lpcDefine
syn region lpcCppBracket transparent start='\[' skip='\\$' excludenl end=']' end='$' contained contains=ALLBUT,@lpcParenGroup,lpcErrInParen,lpcParen,lpcBracket,lpcString,@lpcEfunGroup,lpcApplies,lpcFuncName,lpcKeywdError
syn match lpcErrInBracket display contained "[);{}]"
" Nodule: Numbers {{{1
" integer number, or floating point number without a dot and with "f".
syn case ignore
syn match lpcNumbers display transparent "\<\d\|\.\d" contains=lpcNumber,lpcFloat,lpcOctalError,lpcOctal
" Same, but without octal error (for comments)
syn match lpcNumbersCom display contained transparent "\<\d\|\.\d" contains=lpcNumber,lpcFloat,lpcOctal
syn match lpcNumber display contained "\d\+\(u\=l\{0,2}\|ll\=u\)\>"
" hex number
syn match lpcNumber display contained "0x\x\+\(u\=l\{0,2}\|ll\=u\)\>"
" Flag the first zero of an octal number as something special
syn match lpcOctal display contained "0\o\+\(u\=l\{0,2}\|ll\=u\)\>" contains=lpcOctalZero
syn match lpcOctalZero display contained "\<0"
syn match lpcFloat display contained "\d\+f"
" floating point number, with dot, optional exponent
syn match lpcFloat display contained "\d\+\.\d*\(e[-+]\=\d\+\)\=[fl]\="
" floating point number, starting with a dot, optional exponent
syn match lpcFloat display contained "\.\d\+\(e[-+]\=\d\+\)\=[fl]\=\>"
" floating point number, without dot, with exponent
syn match lpcFloat display contained "\d\+e[-+]\=\d\+[fl]\=\>"
" flag an octal number with wrong digits
syn match lpcOctalError display contained "0\o*[89]\d*"
syn case match
" Nodule: Comment string {{{1
" lpcCommentGroup allows adding matches for special things in comments
syn keyword lpcTodo contained TODO FIXME XXX
syn cluster lpcCommentGroup contains=lpcTodo
if exists("c_comment_strings")
" A comment can contain lpcString, lpcCharacter and lpcNumber.
syntax match lpcCommentSkip contained "^\s*\*\($\|\s\+\)"
syntax region lpcCommentString contained start=+L\=\\\@<!"+ skip=+\\\\\|\\"+ end=+"+ end=+\*/+me=s-1 contains=lpcSpecial,lpcCommentSkip
syntax region lpcComment2String contained start=+L\=\\\@<!"+ skip=+\\\\\|\\"+ end=+"+ end="$" contains=lpcSpecial
syntax region lpcCommentL start="//" skip="\\$" end="$" keepend contains=@lpcCommentGroup,lpcComment2String,lpcCharacter,lpcNumbersCom,lpcSpaceError
syntax region lpcComment matchgroup=lpcCommentStart start="/\*" matchgroup=NONE end="\*/" contains=@lpcCommentGroup,lpcCommentStartError,lpcCommentString,lpcCharacter,lpcNumbersCom,lpcSpaceError
else
syn region lpcCommentL start="//" skip="\\$" end="$" keepend contains=@lpcCommentGroup,lpcSpaceError
syn region lpcComment matchgroup=lpcCommentStart start="/\*" matchgroup=NONE end="\*/" contains=@lpcCommentGroup,lpcCommentStartError,lpcSpaceError
endif
" keep a // comment separately, it terminates a preproc. conditional
syntax match lpcCommentError display "\*/"
syntax match lpcCommentStartError display "/\*"me=e-1 contained
" Nodule: Pre-processor {{{1
syn region lpcPreCondit start="^\s*#\s*\(if\|ifdef\|ifndef\|elif\)\>" skip="\\$" end="$" end="//"me=s-1 contains=lpcComment,lpcCppString,lpcCharacter,lpcCppParen,lpcParenError,lpcNumbers,lpcCommentError,lpcSpaceError
syn match lpcPreCondit display "^\s*#\s*\(else\|endif\)\>"
if !exists("c_no_if0")
syn region lpcCppOut start="^\s*#\s*if\s\+0\+\>" end=".\|$" contains=lpcCppOut2
syn region lpcCppOut2 contained start="0" end="^\s*#\s*\(endif\>\|else\>\|elif\>\)" contains=lpcSpaceError,lpcCppSkip
syn region lpcCppSkip contained start="^\s*#\s*\(if\>\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*#\s*endif\>" contains=lpcSpaceError,lpcCppSkip
endif
syn region lpcIncluded display contained start=+"+ skip=+\\\\\|\\"+ end=+"+
syn match lpcIncluded display contained "<[^>]*>"
syn match lpcInclude display "^\s*#\s*include\>\s*["<]" contains=lpcIncluded
syn match lpcLineSkip "\\$"
syn cluster lpcPreProcGroup contains=lpcPreCondit,lpcIncluded,lpcInclude,lpcDefine,lpcErrInParen,lpcErrInBracket,lpcUserLabel,lpcSpecial,lpcOctalZero,lpcCppOut,lpcCppOut2,lpcCppSkip,lpcFormat,lpcNumber,lpcFloat,lpcOctal,lpcOctalError,lpcNumbersCom,lpcString,lpcCommentSkip,lpcCommentString,lpcComment2String,@lpcCommentGroup,lpcCommentStartError,lpcParen,lpcBracket,lpcMulti,lpcKeywdError
syn region lpcDefine start="^\s*#\s*\(define\|undef\)\>" skip="\\$" end="$" end="//"me=s-1 contains=ALLBUT,@lpcPreProcGroup
if exists("lpc_pre_v22")
syn region lpcPreProc start="^\s*#\s*\(pragma\>\|echo\>\)" skip="\\$" end="$" keepend contains=ALLBUT,@lpcPreProcGroup
else
syn region lpcPreProc start="^\s*#\s*\(pragma\>\|echo\>\|warn\>\|error\>\)" skip="\\$" end="$" keepend contains=ALLBUT,@lpcPreProcGroup
endif
" Nodule: User labels {{{1
" Highlight Labels
" User labels in LPC is not allowed, only "case x" and "default" is supported
syn cluster lpcMultiGroup contains=lpcIncluded,lpcSpecial,lpcCommentSkip,lpcCommentString,lpcComment2String,@lpcCommentGroup,lpcCommentStartError,lpcUserCont,lpcUserLabel,lpcBitField,lpcOctalZero,lpcCppOut,lpcCppOut2,lpcCppSkip,lpcFormat,lpcNumber,lpcFloat,lpcOctal,lpcOctalError,lpcNumbersCom,lpcCppParen,lpcCppBracket,lpcCppString,lpcKeywdError
syn region lpcMulti transparent start='\(case\|default\|public\|protected\|private\)' skip='::' end=':' contains=ALLBUT,@lpcMultiGroup
syn cluster lpcLabelGroup contains=lpcUserLabel
syn match lpcUserCont display "^\s*lpc:$" contains=@lpcLabelGroup
" Don't want to match anything
syn match lpcUserLabel display "lpc" contained
" Nodule: Initializations {{{1
if exists("c_minlines")
let b:c_minlines = c_minlines
else
if !exists("c_no_if0")
let b:c_minlines = 50 " #if 0 constructs can be long
else
let b:c_minlines = 15 " mostly for () constructs
endif
endif
exec "syn sync ccomment lpcComment minlines=" . b:c_minlines
" Make sure these options take place since we no longer depend on file type
" plugin for C
setlocal cindent
setlocal fo-=t fo+=croql
setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://
set cpo-=C
" Win32 can filter files in the browse dialog
if has("gui_win32") && !exists("b:browsefilter")
let b:browsefilter = "LPC Source Files (*.c *.d *.h)\t*.c;*.d;*.h\n" .
\ "LPC Data Files (*.scr *.o *.dat)\t*.scr;*.o;*.dat\n" .
\ "Text Documentation (*.txt)\t*.txt\n" .
\ "All Files (*.*)\t*.*\n"
endif
" Nodule: Highlight links {{{1
" Define the default highlighting.
" For version 5.7 and earlier: only when not done already
" For version 5.8 and later: only when an item doesn't have highlighting yet
if version >= 508 || !exists("did_lpc_syn_inits")
if version < 508
let did_lpc_syn_inits = 1
command -nargs=+ HiLink hi link <args>
else
command -nargs=+ HiLink hi def link <args>
endif
HiLink lpcModifier lpcStorageClass
HiLink lpcQuotedFmt lpcFormat
HiLink lpcFormat lpcSpecial
HiLink lpcCppString lpcString " Cpp means
" C Pre-Processor
HiLink lpcCommentL lpcComment
HiLink lpcCommentStart lpcComment
HiLink lpcUserLabel lpcLabel
HiLink lpcSpecialCharacter lpcSpecial
HiLink lpcOctal lpcPreProc
HiLink lpcOctalZero lpcSpecial " LPC will treat octal numbers
" as decimals, programmers should
" be aware of that.
HiLink lpcEfunError lpcError
HiLink lpcKeywdError lpcError
HiLink lpcOctalError lpcError
HiLink lpcParenError lpcError
HiLink lpcErrInParen lpcError
HiLink lpcErrInBracket lpcError
HiLink lpcCommentError lpcError
HiLink lpcCommentStartError lpcError
HiLink lpcSpaceError lpcError
HiLink lpcSpecialError lpcError
HiLink lpcErrFunc lpcError
" HiLink lpcOldEfuns lpc_efuns
HiLink lpcOldEfuns lpcReserved
HiLink lpcNewEfuns lpcFunction
HiLink lpcCompatEfuns lpcFunction
HiLink lpcNativeEfuns lpcFunction
HiLink lpcSimulEfuns lpcFunction
HiLink lpc_efuns lpcFunction
HiLink lpcReserved lpcPreProc
HiLink lpcTextString lpcString " This should be preprocessors, but
HiLink lpcArrayString lpcPreProc " let's make some difference
" between text and array
HiLink lpcIncluded lpcString
HiLink lpcCommentString lpcString
HiLink lpcComment2String lpcString
HiLink lpcCommentSkip lpcComment
HiLink lpcCommentFunc lpcComment
HiLink lpcCppSkip lpcCppOut
HiLink lpcCppOut2 lpcCppOut
HiLink lpcCppOut lpcComment
" Standard type below
HiLink lpcApplies Special
HiLink lpcCharacter Character
HiLink lpcComment Comment
HiLink lpcConditional Conditional
HiLink lpcConstant Constant
HiLink lpcDefine Macro
HiLink lpcError Error
HiLink lpcFloat Float
HiLink lpcFunction Function
HiLink lpcIdentifier Identifier
HiLink lpcInclude Include
HiLink lpcLabel Label
HiLink lpcNumber Number
HiLink lpcOperator Operator
HiLink lpcPreCondit PreCondit
HiLink lpcPreProc PreProc
HiLink lpcRepeat Repeat
HiLink lpcStatement Statement
HiLink lpcStorageClass StorageClass
HiLink lpcString String
HiLink lpcStructure Structure
HiLink lpcSpecial LineNr
HiLink lpcTodo Todo
HiLink lpcType Type
delcommand HiLink
endif
" Nodule: This is the end nodule. {{{1
let b:current_syntax = "lpc"
" vim:ts=8:nosta:sw=2:ai:si:
" vim600:set fdm=marker: }}}1

152
etc/lpc.xml Normal file
View File

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd">
<!--
=============================================================================
File: lpc.xml
URL: http://www.metamorpher.de/files/lpc.xml
Description: Syntax Highlighting for Lars Pensjo C (LPC)
It is used in Multi User Dungeons which use LDMud as Gamedriver.
For more information, see LDMud project: http://www.bearnip.com
For best highlighting results, configure colors yourself.
Author: Andreas Klauer (Andreas.Klauer@metamorpher.de)
Changed: 2004-04-26
=============================================================================
-->
<language name="LPC" version="0.72" kateversion="2.2.1"
section="Sources" extensions="*.c;*.h;*.inc;*.o">
<highlighting>
<!-- Keyword Lists: -->
<list name="modifiers">
<item> private </item>
<item> protected </item>
<item> static </item>
<item> public </item>
<item> nomask </item>
<item> varargs </item>
<item> nosave </item>
<item> virtual </item>
</list>
<list name="types">
<item> void </item>
<item> int </item>
<item> status </item>
<item> string </item>
<item> object </item>
<item> array </item>
<item> mapping </item>
<item> closure </item>
<item> symbol </item>
<item> float </item>
<item> mixed </item>
</list>
<list name="keywords">
<item> break </item>
<item> continue </item>
<item> return </item>
<item> if </item>
<item> else </item>
<item> for </item>
<item> foreach </item>
<item> do </item>
<item> while </item>
<item> switch </item>
<item> case </item>
<item> inherit </item>
<item> default </item>
<item> variables </item>
<item> functions </item>
<item> publish </item>
<item> nolog </item>
</list>
<!-- Parsing Rules: -->
<contexts>
<context name="Normal" attribute="Default" lineEndContext="#stay">
<Detect2Chars attribute="Single-Line comments" context="Comment1" char="/" char1="/" />
<Detect2Chars attribute="Multi-Line comments" context="Comment2" char="/" char1="*" />
<keyword String="modifiers" attribute="Modifiers" context="#stay" />
<keyword String="types" attribute="Datatype" context="#stay" />
<keyword String="keywords" attribute="Keywords" context="#stay" />
<RegExpr String="^#" context="Preprocessor" attribute="Preprocessor" />
<Float attribute="Floats" context="#stay">
<AnyChar String="fFeE" context="#stay" />
</Float>
<RegExpr String="0b[01]+" attribute="Binary" context="#stay" />
<RegExpr String="0x[0-9a-fA-F]+" attribute="Hexadecimal" context="#stay" />
<RegExpr String="0o[0-7]+" attribute="Octal" context="#stay" />
<Int attribute="Integer" context="#stay" />
<RegExpr String="#'[^\t ][^\t ,);}\]/]*" attribute="Closure" context="#stay" />
<DetectChar attribute="Strings" context="String1" char="&quot;" />
<HlCStringChar attribute="Char" context="#stay" />
</context>
<context name="Comment1" attribute="Single-Line comments" lineEndContext="#pop">
<LineContinue attribute="Single-Line comments" context="#stay" />
<RegExpr attribute="Comment-Keywords" context="#stay" String="^[A-Z]+:" />
</context>
<context name="Comment2" attribute="Multi-Line comments" lineEndContext="#stay">
<Detect2Chars attribute="Multi-Line comments" context="#pop" char="*" char1="/"/>
<RegExpr attribute="Comment-Keywords" context="#stay" String="^[A-Z]+:" />
</context>
<context name="Preprocessor" attribute="Preprocessor" lineEndContext="#pop">
<LineContinue attribute="Preprocessor" context="#stay" />
<Detect2Chars attribute="Single-Line comments" context="Comment1" char="/" char1="/" />
<Detect2Chars attribute="Multi-Line comments" context="Comment2" char="/" char1="*" />
<keyword String="modifiers" attribute="Modifier" context="#stay" />
<keyword String="types" attribute="Datatype" context="#stay" />
<keyword String="keywords" attribute="Keywords" context="#stay" />
<DetectChar attribute="Preprocessor-Strings" context="String2" char="&quot;" />
</context>
<context name="String1" attribute="Strings" lineEndContext="#pop">
<LineContinue attribute="Default" context="#stay" />
<Detect2Chars char="\" char1="\" attribute="Strings" context="#stay" />
<Detect2Chars char="\" char1="&quot;" attribute="Strings" context="#stay" />
<DetectChar char="&quot;" attribute="Strings" context="#pop" />
</context>
<context name="String2" attribute="Preprocessor-Strings" lineEndContext="#pop">
<LineContinue attribute="Default" context="#stay" />
<Detect2Chars char="\" char1="\" attribute="Preprocessor-Strings" context="#stay" />
<Detect2Chars char="\" char1="&quot;" attribute="Preprocessor-Strings" context="#stay" />
<DetectChar char="&quot;" attribute="Preprocessor-Strings" context="#pop" />
</context>
</contexts>
<!-- Color Settings: -->
<itemDatas>
<itemData name="Default" defStyleNum="dsNormal" />
<itemData name="Single-Line comments" defStyleNum="dsComment" />
<itemData name="Multi-Line comments" defStyleNum="dsComment" />
<itemData name="Comment-Keywords" defStyleNum="dsKeyword" />
<itemData name="Modifier" defStyleNum="dsDataType" />
<itemData name="Datatype" defStyleNum="dsDataType" />
<itemData name="Keywords" defStyleNum="dsKeyword" />
<itemData name="Preprocessor" defStyleNum="dsOthers" />
<itemData name="Floats" defStyleNum="dsFloat" />
<itemData name="Binary" defStyleNum="dsBaseN" />
<itemData name="Hexadecimal" defStyleNum="dsBaseN" />
<itemData name="Octal" defStyleNum="dsBaseN" />
<itemData name="Integer" defStyleNum="dsDecVal" />
<itemData name="Closure" defStyleNum="dsOthers" />
<itemData name="Strings" defStyleNum="dsString" />
<itemData name="Preprocessor-Strings" defStyleNum="dsString" />
<itemData name="Char" defStyleNum="dsChar" />
</itemDatas>
</highlighting>
<!-- This is not for highlighting, but for detecting comments.
It allows Kate to hide comments if the user wished to do so. -->
<general>
<comments>
<comment name="singleLine" start="//" />
<comment name="multiLine" start="/*" end="*/" />
</comments>
<keywords casesensitive="1" />
</general>
</language>
<!-- === End of file. === -->

96
etc/memusage Executable file
View File

@ -0,0 +1,96 @@
#!/usr/bin/perl -w
# originating from MorgenGrauen
# 11.06.02 Fiona more robust parsing
$MUDLIBDIR = "/usr/mud/mudlib/";
$HOMES = "players";
$DOMAINS = "d";
$OUTPUTDIR = $MUDLIBDIR."tmp/";
$| = 1;
printf("Creating Object-Lists ... ");
%mem=(); %inst=(); %envs=(); %TotalMem=(); $MemSum=0;
%wizobj=();%wizmem=();%domobj=();%dommem=();
open(DUMP,$MUDLIBDIR."OBJ_DUMP");
for (<DUMP>)
{
chop;
#@line=split(' ');
print("matcherr: $_\n")
unless $_ =~ /^([^ ]+) \D*(\d+)\D*(\d+)\D*\d+ +(HB)? +(\S*)/;
$env=$5;
$env.=' *HB*' if ($4);
@fname=split('#',$1);
$mem{$1}=$2;
$inst{$fname[0]}+=1;
$TotalMem{$fname[0]}+=$2;
$envs{$1}=$5;
$MemSum+=$2;
@path=split("/",$1);
if ($path[0] eq $HOMES)
{
$wizobj{$path[1]}++;
$wizmem{$path[1]}+=$2;
}
if ($path[0] eq $DOMAINS)
{
$wizobj{$path[2]}++;
$wizmem{$path[2]}+=$2;
$domobj{$path[1]}++;
$dommem{$path[1]}+=$2;
}
}
printf("done\nMEMORY list is being created ... sorting ... ");
@keys=sort {$mem{$b} <=> $mem{$a}} keys %mem;
print "dumping ... ";
open(DUMP,">".$OUTPUTDIR."MEMORY_SORTED");
printf DUMP "Memory usage according to OBJ_DUMP is %d bytes.\n",$MemSum;
foreach $key (@keys)
{
printf DUMP "%-30s: mem=%4d, env=%s\n", $key, $mem{$key}, $envs{$key};
}
close(DUMP);
printf("done\nCOUNT_LIST is being created ... sorting ... ");
@keys=sort {$inst{$b} <=> $inst{$a}} keys %inst;
print "dumping ... ";
open(DUMP,">".$OUTPUTDIR."COUNT_SORTED");
foreach $key (@keys)
{
printf DUMP "%3d instances using %4d Bytes: %s\n",$inst{$key},$TotalMem{$key},$key;
}
close(DUMP);
printf("done\nTOTAL_MEM_LIST is being created ... sorting ... ");
@keys=sort {$TotalMem{$b} <=> $TotalMem{$a}} keys %inst;
print "dumping ... ";
open(DUMP,">".$OUTPUTDIR."TOTAL_MEM");
foreach $key (@keys)
{
printf DUMP "%3d instances using %4d Bytes: %s\n",$inst{$key},$TotalMem{$key},$key;
}
close(DUMP);
printf("done\nDumping OWNER list ... ");
@keys=sort {$wizmem{$b} <=> $wizmem{$a}} keys %wizmem;
open(DUMP,">".$OUTPUTDIR."BY_NAME");
printf DUMP "How much Memory does each Wizard use ?\n";
foreach $key (@keys)
{
printf DUMP "%-14s: %4d objects using %9d bytes\n", $key,$wizobj{$key},$wizmem{$key};
}
printf DUMP "\n\nHow much Memory does each domain use ?\n";
@keys=sort {$dommem{$b} <=> $dommem{$a}} keys %dommem;
foreach $key (@keys)
{
printf DUMP "%-14s: %4d objects using %9d bytes\n", $key,$domobj{$key},$dommem{$key};
}
close(DUMP);
print "done\n";

94
etc/psyclpc.ebuild Normal file
View File

@ -0,0 +1,94 @@
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /CVS/anonCVS/psyclpc/etc/psyclpc.ebuild,v 1.1 2007/08/14 09:03:30 lynx Exp $
#
# psyclpc is a programming language for intense multi-user network applications
# such as psyced. it's a recent fork of LDMUD with some features and many
# bug fixes. we kept it compatible to LDMUD, so you can run a MUD with it, too.
#
# Suggestions? tell psyc://psyced.org/~lynX
#
# WARNING/REMINDER to myself: When checking in a new version of this file
# into CVS I have to run 'make up' in the gentoo download tar, as it also
# relinks all the psyclpc/psyclpc-VERSION.ebuild files. 'cvs update' alone
# wouldn't do that.
#
# this ebuild file is available in both psyclpc/etc and psyced/config/gentoo.
# psyced also provides installation automations.
inherit toolchain-funcs eutils
DESCRIPTION="psycLPC is a multi-user network server programming language"
HOMEPAGE="http://lpc.psyc.eu/
# using the filename of the ebuild here!
# so better give it numbers which are actually
# available in http://www.psyced.org/files/
SRC_URI="http://www.psyced.org/files/${P}.tar.bz2"
LICENSE="GPL-2"
SLOT="0"
# haven't checked for real..
# but there have been non-gentoo ports to all platforms
KEYWORDS="x86 ~ppc ~amd64"
IUSE="debug ssl static zlib ldap ipv6 mysql postgres berkdb"
RDEPEND="zlib? ( sys-libs/zlib )
ssl? ( dev-libs/openssl )
ldap? ( net-nds/openldap )
berkdb? ( sys-libs/db )
mysql? ( dev-db/mysql )
postgres? ( dev-db/postgresql )"
DEPEND="${RDEPEND}
>=sys-devel/flex-2.5.4a-r5
>=sys-devel/bison-1.875
>=sys-devel/gettext-0.12.1"
#MYS="/var/tmp/portage/${P}/work/${P}/src"
MYS="${S}/src"
src_compile() {
cd "${MYS}"
# use berkdb >&/dev/null && myopts="${myopts} --enable-db"
# use mysql >&/dev/null && myopts="${myopts} --enable-mysql" || myopts="${myopts} --disable-mysql"
# use postgres >&/dev/null && myopts="${myopts} --enable-pgsql"
# use ldap >&/dev/null && myopts="${myopts} --enable-ldap"
# use ipv6 >&/dev/null && myopts="${myopts} --enable-ipv6"
use zlib && {
einfo "Compiling ${P} with zlib (MCCP) support."
myopts="${myopts} --enable-use-mccp"
}
use ssl && {
einfo "Compiling ${P} with SSL support."
myopts="${myopts} --enable-use-tls=yes"
}
use mysql && {
einfo "Compiling ${P} with mySQL support."
myopts="${myopts} --enable-use-mysql"
}
use postgres && {
einfo "Compiling ${P} with PostgreSQL support."
myopts="${myopts} --enable-use-pgsql"
}
use debug && {
append-flags -O -ggdb -DDEBUG
RESTRICT="${RESTRICT} nostrip"
myopts="${myopts} --enable-debug"
}
# runs configure
echo ${myopts}
# choice of settings should be configurable.. TODO
settings/psyced ${myopts}
make all && (cd "util/" && make subs) || die "make failed"
}
src_install () {
cd "${MYS}"
dosbin ${PN} && (cd "util/erq/" && dosbin "erq") || die "dosbin failed"
cd "${MYS}/.."
# only the interesting files
dodoc HELP CHANGELOG psyclpc.1
# maybe we should install etc/lpc.vim?
# and what about the man file?
}

209
etc/savefile-parse.pl Normal file
View File

@ -0,0 +1,209 @@
#!/usr/bin/perl -w
######
#
# Parse a mudmode (save_value) string
#
# A single variable value is parsed and represented as perl data structure.
# So a string like '({"a",3,(["b":2,]),})' gets ['a',3,{'b'=>2}]
#
# Fiona 23-Mai-03
#
use Data::Dumper;
$parse_err = undef; # Global error messages
%unquote = (
'r' => "\r",
'f' => "\f",
'v' => "\v",
'n' => "\n",
't' => "\t",
'b' => "\b",
'a' => "\a",
);
# parse a single value
#
# Knows: int, string, array, float, mapping
# (Todo: ref_to_array/mapping, closures)
#
# arguments: source string
# reference to start index of value
# returns value in perl
# set start index to next char (if any) or -1
#
# If an error occured -1 will be returned and $parse_err set
sub get_value {
my ($offsp, $str, $ret, $ret2, $data);
$str = $_[0];
$offsp = $_[1];
# check for float
#
# [German:Koresh@OuterSpace] OS would encode it as #-1.00000001e-01# but
# not sure everybody does it this way.
# [German:Fiona] means ({-0.1}) becomes ({#-1.00000001e-01#,}) ?
# [German] Koresh@OuterSpace nods wildly
# [German] Koresh@OuterSpace also notes that mudos does not seem to include
# the # in floats: it just writes it as ({-1.00000e-08,})
#
# LDmud float
# -9.999999997672e-02=fffd:9999999a
pos($str) = $$offsp;
$str =~ m/\G#?(-?\d.\d*[eE][-+]\d\d)(#|=[0-9a-f:]+)?/sg;
if (defined $1) {
$$offsp = pos($str);
return $1;
}
# check for int (check *after* floats)
pos($str) = $$offsp;
$str =~ m/\G(-?\d+)/sg;
if (defined $1) {
$$offsp = pos($str);
return $1;
}
# check for string
pos($str) = $$offsp;
if ($str =~ m/\G"((?:[^"\\]+|\\.)*)"/sg ) {
$$offsp = pos($str);
# unquote string
$ret = $1;
$ret =~ s/\\(.)/$unquote{$1}||$1/esg;
return $ret;
}
# check for array
pos($str) = $$offsp;
if ($str =~ m/\G\({/sg ) {
$$offsp = pos($str);
$data = [];
if ($str =~ m/\G}\)/sg ) {
$$offsp += 2;
return $data;
}
# recurse array
while (1) {
$ret = get_value($str, $offsp);
return -1 if ($parse_err || $offsp == -1);
push @{$data}, $ret;
pos($str) = $$offsp;
if (not ($str =~ m/\G,/sg )) {
pos($str) = $$offsp;
$str =~ m/\G(.{0,8})/sg;
$parse_err = "Comma missing in array near '$1'";
return -1;
}
$$offsp += 1;
if ($str =~ m/\G}\)/sg ) {
$$offsp += 2;
return $data;
}
}
# notreached
}
# check for mapping
#
# MudOS has no 2dimensional Mappings, so we dont support them
# (perl is unable to represent them anyhow)
# Zero-width mappings are impossible with mudmode/perl, so emulate them.
pos($str) = $$offsp;
if ($str =~ m/\G\(\[/sg ) {
$$offsp = pos($str);
$data = {};
if ($str =~ m/\G]\)/sg ) {
$$offsp += 2;
return $data;
}
# recurse array
while (1) {
$ret = get_value($str, $offsp);
return -1 if ($parse_err || $offsp == -1);
pos($str) = $$offsp;
if (not ($str =~ m/\G[:,]/sg )) {
pos($str) = $$offsp;
if ($str =~ m/\G;/sg ) {
$parse_err = 'Multidimensional mapping not supported near ';
} else {
$parse_err = 'Colon missing in mapping near ';
}
pos($str) = $$offsp;
$str =~ m/\G(.{0,8})/sg;
$parse_err = $parse_err . "'$1'";
return -1;
}
$$offsp += 1;
pos($str) = $$offsp-1;
if ($str =~ m/\G,/sg ) { # zero width, gets simulated...
$ret2 = 0;
} else {
$ret2 = get_value($str, $offsp);
return -1 if ($parse_err || $offsp == -1);
pos($str) = $$offsp;
if (not ($str =~ m/\G,/sg )) {
pos($str) = $$offsp;
$str =~ m/\G(.{0,8})/sg;
$parse_err = "Comma missing in mapping near '$1'";
return -1;
}
$$offsp += 1;
}
$$data{$ret} = $ret2;
if ($str =~ m/\G]\)/sg ) {
$$offsp += 2;
return $data;
}
}
# notreached
}
# check for parse error
pos($str) = $$offsp;
$str =~ m/\G(.{1,8})/sg;
if (defined $1) {
$parse_err = "Unknown variable type near '$1'";
return -1;
}
# end of string
$$offsp = -1;
return -1;
}
######
#
# Sample usage
#
$str = '({1234,45,({12,-1,({0,}),}),"fla\nb\"ber",-1.110999999642e+02=7:90e66667,({}),(["b":"a","c":({1,-2,}),]),([1,2,3,]),})';
#$str='({"error",5,"*gjs",0,"Test-PerlMud-i3",0,"unk-src","router does not know you",({"startup-req-3",5,"Test-PerlMud-i3",0,"",0,1016,4156424,330,0,0,0,"PerlLib v1","PerlLib v1","Perlv5.6.1","Perl","restricted access","castaway@desert-island.m.isar.de",(["channel":1,"nntp":0,"file":0,"amcp":0,"rcp":0,"emoteto":1,"auth":0,"who":1,"smtp":0,"mail":0,"finger":1,"ucache":1,"locate":1,"news":0,"http":0,"ftp":0,"tell":1,]),0,}),})';
$posi = 0;
$ret = get_value($str, \$posi);
if ($parse_err) {
print("ERROR $parse_err\n");
} else {
print(Dumper($ret));
}

80
mudlib/ACCESS.ALLOW Normal file
View File

@ -0,0 +1,80 @@
# ACCESS.ALLOW - Game access allowance rules
#----------------------------------------------------------------------------
# Access to the game is based on the user's IP address and the current time.
# These are matched against a set of rules and if a match is detected, a
# proper message is sent back and the connection is shutdown.
#
# This facility is active only if ACCESS_CONTROL has been defined in config.h
# If ACCESS_LOG is defined in config.h, all checks and their results are
# logged in the specified file.
#
# The rules are read from the file ACCESS_FILE (defined in config.h,
# typically "ACCESS.ALLOW" with a name relative to the mudlib directory).
# Every line specifies one rule and has to follow the syntax given below.
# Lines with a '#' as first character count as comments and are ignored, as
# are lines which do not conform to the rule syntax (but except for empty
# lines this should be relied upon).
#
# The rule file is (re)read whenever the gamedriver detects a change in its
# timestamp.
#
# The syntax for a rule is (no leading whitespace allowed!):
#
# <ipnum>:[p<port>]:<class>:<max>:<start>:<end>:<text>
# <ipnum>:[p<port>]:<class>:<max>:h<hours>:w<days>:m=<text>
#
# where
# ipnum: <byte>.<byte>.<byte>.<byte>, with byte = * or number
# There is only loose error checking - specifying an illegal
# address will have interesting consequences, but would
# most likely cause no error to occur.
# port: the port number to which the connection is made. Omission
# means 'any port'.
# class: number
# max: the maximum number of users, a number. The value -1 allows
# an unlimited number of users.
# start: hour this rule starts to be valid (0..23).
# end: hour this rule ceases to be valid (0..23).
# Setting both start and end to 0 skips any time check.
# hours: hours this rule is valid.
# This form allows several entries, separated with a ','.
# Every entry can be a single hour (0..23), or a range in the
# form '<start>-<end>'
# Omitting the entry skips any time check.
# days: the days this rule is valid.
# The syntax is similar to <hours> except for the
# allowable values: the days Sunday..Saturday are given as
# the numbers 0..6.
# Omitting the entry skips any day check.
# text: string to send if the rule matches.
#
# A class is defined by the first rule using it's number. This
# definition specifies the allowable <max>imum of users and the <text>
# to send. Subsequent rules for the same class just add new ipnumber/
# time rules, but don't change <max> or <text>
#
# ORDER MATTERS. That means if you allow 129.*.*.*, you have to put
# any restrictions on 129.132.*.* BEFORE this rule.
#
# Addresses not matching any rule at all are not allowed to connect. To get
# around this, add an appropriate 'allow-all' rule *.*.*.* at the very end.
#
# A typical rulefile would look like this one:
# SPARC cluster has access denied. Class 1
129.132.122.*:1:0:0:0:LPMUD access denied for your cluster.
# CALL-1A0 has access limited to some maximum, for now 5 logins. Class 2
129.132.106.*:2:5:8:20:Sorry, LPMUD is currently full.
# CALL-1A0 at all other times, its a 10 limit.
# Due to the rule order, this is effectively limited to times
# outside 8-20.
129.132.106.*:3:10:0:0:Sorry, LPMUD is currently full.
# No more than 5 users allowed from localhost while working hours :-)
127.0.0.1:42:5:h8-12,13-18:w1-5:m=Pick a better time.
# Everybody else is welcome.
*.*.*.*:0:-1:0:0:This message should never be printed.

22
mudlib/README Normal file
View File

@ -0,0 +1,22 @@
This directory holds various example and support files for mudlibs.
Especially important is the sys/ subdirectory with the driver-related
include files.
Other files are:
ACCESS.ALLOW : a typical access control file.
master_skeleton.c: a skeleton master, documenting all master lfuns.
telnet.h, telnetneg.c: the Wunderland telnet module, a complete implementation
of the telnet protocol.
test_master.c : a minimal test master for driver tests.
simul_efun-dr.c : a very old simul_efun file for a very old DR mudlib.
erq-tool.c : for 2.4.5 muds, a tool for interactive erq experiments.
dhrystone.c : an implementation of Dhrystone, called by the
test_master.
astar.c : an implementation of the A* pathfinding algorithm.
pgsql.c : example for using PostgreSQL
dns_resolve.c : a simul-efun for non-block DNS lookups
query_ip_name.c : a simul-efun for IPv4/IPv6 name lookups
uni-crasher/ : A stress test program, see the README in this dir.

196
mudlib/astar.c Normal file
View File

@ -0,0 +1,196 @@
#if 0
--------------------------------------------------------------------------
Date: Thu, 13 Dec 2001 00:34:12 -0700
From: Acius <helpsfamily@attbi.com>
A while back we were talking about eventually putting path-finding in
the driver, but I don't know if anyone came up with anything really
specific (I might add that I've been off the mailing list for a little
while now, thanks to @Home's problems). I wanted path-finding for my
MUD, and since it sounded like it might be a while until Lars has enough
time to play with it, I've implemented A-star in LP/C. The code is
attached to this message.
I have a couple reasons for posting the code: Firstly, anyone who might
want to use it can try it, and if they post their modifications and
bugfixes, I get better code for free :-). Also, it serves as an
interface and behavior suggestion for future code to be put into the
driver. I wrote it with this idea in mind, and I have attempted to make
the code a very general way to do 2d path-finding. The code could be
placed in a simul_efun for now, and simply commented out or removed when
and if driver path-finding code comes on line.
The parameters are:
* A string, giving the map on which you're doing the search
* The x, y of the starting location
* The x, y of the goal location
* A mapping of ([ character: cost ]) for all of the characters used in
the map string. All characters not included in the mapping are assumed
to be walls. A cost of 0 might not get the best path if you use it,
since Manhattan distance is used to guide the search and it will
overestimate (go read a good article on A-star).
Here's a quick example of how to use it:
.*.#.
.#...
...
I want to get from the upper left corner (0, 0) to the upper right
corner (4, 0), and I need to know the path to get there. The #'s are
walls, and may not be crossed. The '*' may be crossed, but it is a
"poisonous" tile and should not be crossed if there is an alternative.
Note that the grid doesn't have to be square; the function will append
each line with "\27"'s to make it square.
Here's how to make a function call to get this path:
string path;
path =
find_path(".*.#.\n.#...\n...", 0, 0, 4, 0, ([ '.': 1, '*': 100 ]));
if( path )
write("You should go "+path+"\n");
else
write("No path could be found.\n");
On my MUD, the call to find_path returns the string "sseeneen". If you
lower the cost of '*' to 5 (just change the 100 to a 5), then it returns
the string "eeseen".
If there are any other questions, please email me; this message is
getting long enough already. I particularly want to hear from you if you
get it working (or can't!) and if you find bugs or ways to make it more
efficient (it is not very efficient). I tried not to put in anything
MUDlib-specific, but sometimes I forget.
-- Acius
--------------------------------------------------------------------------
#endif
string find_path( string map, int startx, int starty, int goalx, int goaly, mapping costs ) {
// split_map will be an array of equal-length
//strings (will pad spaces to assure this)
string *split_map;
// i is for generic loops, map_width is width
// of split_map, goal is the destination point
// (All coordinates are stored as x + y *
// width). currpos is where the algorithm is
// looking, currcost is cost at currpos, newx,
// newy, newpos, and newcost are temps for
// figuring out where to look next.
int i, map_width, start, goal, currpos, currcost, newx, newy, newpos, newcost;
int ineighbor, iparent, iheap;
// closed is mapping from (int)coordinate:
// (int) cost & direction. Note that costs
// > 2^28 will cause undetected overflow
// problems -- if you keep costs reasonable,
// you shouldn't have a problem.
mapping closed;
// The open list, stored as a heap.
// Even-numbered elements hold coordinate information,
// odd-numbered ones give the cost for the previous
// even numbered coordinate.
int *open;
string path;
mixed tmp;
// Process the map into an easier-to-use format.
split_map = explode( map, "\n" );
map_width = 0;
// Find the length of the longest line in the "map"
for( i = sizeof(split_map); i-- ; )
if( map_width < strlen(split_map[i]) ) map_width = strlen(split_map[i]);
// Make all the lines that length by padding with escape characters.
// (Note: I use escapes because they are an unlikely character to be
// chosen for walking over, and unused characters are 'walls')
for( i = sizeof(split_map); i-- ; )
split_map[i] += sprintf( "%" + (map_width-strlen(split_map[i])) + "'\27's", "" );
// Sanity check
if( goalx < 0 || goalx >= map_width || goaly < 0 || goaly >= sizeof(split_map) )
return 0;
// Setup initial state.
start = startx + starty * map_width;
goal = goalx + goaly * map_width;
open = ({ 0, start });
closed = ([ start:0 ]);
while( sizeof(open) && !member(closed, goal) ) {
currcost = open[0];
currpos = open[1];
// Check if done.
if( currpos == goal ) {
closed[currpos] = currcost;
break;
}
// Pop the top cell off the heap.
open[0] = open[<2];
open[1] = open[<1];
open = open[0..<3];
iparent = 0;
iheap = 2;
while( iheap < sizeof(open) ) {
if( open[iparent] > open[iheap] && (iheap + 2 >= sizeof(open) || open[iheap] < open[iheap + 2]) ) {
tmp = open[iparent..iparent+1];
open[iparent..iparent + 1] = open[iheap..iheap + 1];
open[iheap..iheap + 1] = tmp;
}
else if( iheap + 2 < sizeof(open) && open[iparent] > open[iheap + 2] ) {
tmp = open[iparent..iparent+1];
open[iparent..iparent + 1] = open[iheap + 2..iheap + 3];
open[iheap + 2..iheap + 3] = tmp;
}
else
break;
iparent = iheap;
iheap = (iparent + 1) << 1;
}
// Add the neighbors of the popped cell to the heap
// 0 = east, 1 = north, 2 = west, 3 = south
for( ineighbor = 0; ineighbor < 4; ineighbor++ ) {
newx = (currpos % map_width) + ({ 1, 0, -1, 0 })[ineighbor];
newy = (currpos / map_width) + ({ 0, -1, 0, 1 })[ineighbor];
newcost = ({ 0x0, 0x1, 0x2, 0x3 })[ineighbor];
// Out of bounds, ignore it.
if( newx < 0 || newx >= map_width || newy < 0 || newy >= sizeof(split_map) )
continue;
// Solid wall, ignore it.
if( !member(costs, split_map[newy][newx]) ) continue;
newpos = newx + newy * map_width;
// Already checked, ignore it.
if( member(closed, newpos) ) continue;
// Ok, it's legit. Add it to the heap:
newcost |= (currcost & 0xFFFC) + (costs[split_map[newy][newx]] << 2);
newcost -= (abs(currpos % map_width) + abs(currpos / map_width)) << 2;
newcost += (abs(goalx - newx) + abs(goaly - newy)) << 2;
// Mark this cell as 'considered'
closed[newpos] = newcost;
iheap = sizeof(open);
open += ({ newcost, newpos });
if( iheap > 0 )
while( open[iparent = ((iheap >> 1) - 1) & -2] > open[iheap] ) {
tmp = open[iparent..iparent+1];
open[iparent..iparent+1] = open[iheap..iheap+1];
open[iheap..iheap+1] = tmp;
}
}
}
i = goal;
if( !member(closed, i) ) return 0;
path = "";
while( i != start ) {
path = ({ "e", "n", "w", "s" })[closed[i]&0x3] + path;
i += ({ -1, map_width, 1, -map_width })[closed[i]&0x3];
}
return path;
}

365
mudlib/dhrystone.c Normal file
View File

@ -0,0 +1,365 @@
//===========================================================================
// Dhrystone-2.1 Benchmark for LPC
//
// Don't take this too serious :-) Sven C. Dack
//===========================================================================
#define Default_Number_Of_Runs 10000
#pragma strong_types
//===========================================================================
// Support functions to simulate memory allocation and other stuff..
mixed *alloc_array_50() { return allocate(50); }
mixed *alloc_array_50_50() {
mixed *arr;
int i;
for (i = 50, arr = allocate(50); i--; arr[i] = allocate(50));
return arr;
}
mapping alloc_record() {
return ([ "Ptr_Comp": 0, "Discr": 0, "var_1": ({ 0, 0, "" }) ]);
}
mapping copy_record(mapping rec) {
mapping r;
r = copy(rec);
r["var_1"] = ({}) + rec["var_1"];
return r;
}
int times() {
int *ru;
ru = rusage();
return ru[0] + ru[1];
}
//===========================================================================
// The global variables.
#define Ident_1 0
#define Ident_2 1
#define Ident_3 2
#define Ident_4 3
#define Ident_5 4
#define Enum_Comp 0
#define Int_Comp 1
#define Str_Comp 2
mapping Ptr_Glob, Next_Ptr_Glob;
int Int_Glob;
int Bool_Glob;
int Ch_1_Glob, Ch_2_Glob;
mixed *Arr_1_Glob;
mixed *Arr_2_Glob;
int Begin_Time, End_Time, User_Time;
float Milliseconds, Dhrystones_Per_Second;
//===========================================================================
// Prototypes all functions (including those defined later).
void Proc_1(mapping m1);
void Proc_2(int i1);
void Proc_3(mapping m1);
void Proc_4();
void Proc_5();
void Proc_6(int i1, int i2);
void Proc_7(int i1, int i2, int i3);
void Proc_8(mixed *a1, mixed *a2, int i1, int i2);
int Func_1(int i1, int i2);
int Func_2(string s1, string s2);
int Func_3(int i1);
//===========================================================================
float main(int Number_Of_Runs, int silent) {
int Int_1_Loc, Int_2_Loc, Int_3_Loc;
int Ch_Index;
int Enum_Loc;
string Str_1_Loc, Str_2_Loc;
int Run_Index;
if (Number_Of_Runs <= 0)
Number_Of_Runs = Default_Number_Of_Runs;
Arr_1_Glob = alloc_array_50();
Arr_2_Glob = alloc_array_50_50();
Str_1_Loc = "";
Str_2_Loc = "";
Next_Ptr_Glob = alloc_record();
Ptr_Glob = alloc_record();
Ptr_Glob["Ptr_Comp"] = Next_Ptr_Glob;
Ptr_Glob["Discr"] = Ident_1;
Ptr_Glob["var_1"][Enum_Comp] = Ident_3;
Ptr_Glob["var_1"][Int_Comp] = 40;
Ptr_Glob["var_1"][Str_Comp] = "DHRYSTONE PROGRAM, SOME STRING";
Str_1_Loc = "DHRYSTONE PROGRAM, 1'ST STRING";
Arr_2_Glob[8][7] = 10;
if (!silent)
{
write("Dhrystone Benchmark, Version 2.1 (Language: LPC)\n");
write("Execution starts, " + Number_Of_Runs + " runs through Dhrystone\n");
}
Begin_Time = times();
for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) {
Proc_5();
Proc_4();
Int_1_Loc = 2;
Int_2_Loc = 3;
Str_2_Loc = "DHRYSTONE PROGRAM, 2'ND STRING";
Enum_Loc = Ident_2;
Bool_Glob = !Func_2(Str_1_Loc, Str_2_Loc);
while (Int_1_Loc < Int_2_Loc) {
Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
Proc_7(Int_1_Loc, Int_2_Loc, &Int_3_Loc);
Int_1_Loc += 1;
}
Proc_8(Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
Proc_1(Ptr_Glob);
for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) {
if (Enum_Loc == Func_1(Ch_Index, 'C')) {
Proc_6(Ident_1, &Enum_Loc);
Str_2_Loc = "DHRYSTONE PROGRAM, 3'RD STRING";
Int_2_Loc = Run_Index;
Int_Glob = Run_Index;
}
}
Int_2_Loc = Int_2_Loc * Int_1_Loc;
Int_1_Loc = Int_2_Loc / Int_3_Loc;
Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
Proc_2(&Int_1_Loc);
}
End_Time = times();
if (!silent)
{
write("Execution ends.\n");
write("Final values of the variables used in the benchmark:\n\n");
printf("Int_Glob: %d\n", Int_Glob);
printf(" should be: %d\n", 5);
printf("Bool_Glob: %d\n", Bool_Glob);
printf(" should be: %d\n", 1);
printf("Ch_1_Glob: %c\n", Ch_1_Glob);
printf(" should be: %c\n", 'A');
printf("Ch_2_Glob: %c\n", Ch_2_Glob);
printf(" should be: %c\n", 'B');
printf("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
printf(" should be: %d\n", 7);
printf("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
printf(" should be: Number_Of_Runs + 10\n");
#if 0
printf("Ptr_Glob->\n");
printf(" Ptr_Comp: %O\n", Ptr_Glob["Ptr_Comp"]);
printf(" should be: (implementation-dependent)\n");
#endif
printf(" Discr: %d\n", Ptr_Glob["Discr"]);
printf(" should be: %d\n", 0);
printf(" Enum_Comp: %d\n", Ptr_Glob["var_1"][Enum_Comp]);
printf(" should be: %d\n", 2);
printf(" Int_Comp: %d\n", Ptr_Glob["var_1"][Int_Comp]);
printf(" should be: %d\n", 17);
printf(" Str_Comp: %s\n", Ptr_Glob["var_1"][Str_Comp]);
printf(" should be: DHRYSTONE PROGRAM, SOME STRING\n");
#if 0
printf("Next_Ptr_Glob->\n");
printf(" Ptr_Comp: %O\n", Next_Ptr_Glob["Ptr_Comp"]);
printf(" should be: (implementation-dependent), same as above\n");
#endif
printf(" Discr: %d\n", Next_Ptr_Glob["Discr"]);
printf(" should be: %d\n", 0);
printf(" Enum_Comp: %d\n", Next_Ptr_Glob["var_1"][Enum_Comp]);
printf(" should be: %d\n", 1);
printf(" Int_Comp: %d\n", Next_Ptr_Glob["var_1"][Int_Comp]);
printf(" should be: %d\n", 18);
printf(" Str_Comp: %s\n", Next_Ptr_Glob["var_1"][Str_Comp]);
printf(" should be: DHRYSTONE PROGRAM, SOME STRING\n");
printf("Int_1_Loc: %d\n", Int_1_Loc);
printf(" should be: %d\n", 5);
printf("Int_2_Loc: %d\n", Int_2_Loc);
printf(" should be: %d\n", 13);
printf("Int_3_Loc: %d\n", Int_3_Loc);
printf(" should be: %d\n", 7);
printf("Enum_Loc: %d\n", Enum_Loc);
printf(" should be: %d\n", 1);
printf("Str_1_Loc: %s\n", Str_1_Loc);
printf(" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
printf("Str_2_Loc: %s\n", Str_2_Loc);
printf(" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
printf("\n");
}
User_Time = End_Time - Begin_Time;
if (User_Time <= 0) {
if (!silent) {
printf("Your rusage() doesn't seem to work: User_Time is %d.\n", User_Time);
write("\n");
}
} else if (User_Time < (2*100)) {
if (!silent) {
write("Measured time too small to obtain meaningful results\n");
write("Please increase number of runs\n");
write("\n");
}
} else {
Milliseconds = to_float(User_Time) / Number_Of_Runs;
Dhrystones_Per_Second = 1000.0 * Number_Of_Runs / User_Time;
if (!silent) {
printf ("Milliseconds for one run through Dhrystone: ");
printf ("%6.1f \n", Milliseconds);
printf ("Dhrystones per Second: ");
printf ("%6.1f \n", Dhrystones_Per_Second);
}
}
return Dhrystones_Per_Second;
}
void Proc_1(mapping Ptr_Val_Par) {
mapping Next_Record;
Next_Record = Ptr_Val_Par["Ptr_Comp"];
Ptr_Val_Par["Ptr_Comp"] = copy_record(Ptr_Glob);
Ptr_Val_Par["var_1"][Int_Comp] = 5;
Next_Record["var_1"][Str_Comp] = Ptr_Val_Par["var_1"][Str_Comp];
Next_Record["var_1"][Int_Comp] = Ptr_Val_Par["var_1"][Int_Comp];
Next_Record["Ptr_Comp"] = Ptr_Val_Par["Ptr_Comp"];
Proc_3(&(Next_Record["Ptr_Comp"]));
if (Next_Record["Discr"] == Ident_1) {
Next_Record["var_1"][Int_Comp] = 6;
Proc_6( Ptr_Val_Par["var_1"][Enum_Comp],
&(Next_Record["var_1"][Enum_Comp]));
Next_Record["Ptr_Comp"] = Ptr_Glob["Ptr_Comp"];
Proc_7( Next_Record["var_1"][Int_Comp], 10,
&(Next_Record["var_1"][Int_Comp]));
} else
Ptr_Val_Par = copy_record(Ptr_Val_Par["Ptr_Comp"]);
}
void Proc_2(int Int_Par_Ref) {
int Int_Loc, Enum_Loc;
Int_Loc = Int_Par_Ref + 10;
do
if (Ch_1_Glob == 'A') {
Int_Loc -= 1;
Int_Par_Ref = Int_Loc - Int_Glob;
Enum_Loc = Ident_1;
} while (Enum_Loc != Ident_1);
}
void Proc_3(mapping Ptr_Ref_Par) {
if (Ptr_Glob != 0)
Ptr_Ref_Par = Ptr_Glob["Ptr_Comp"];
Proc_7(10, Int_Glob, &(Ptr_Glob["var_1"][Int_Comp]));
}
void Proc_4() {
int Bool_Loc;
Bool_Loc = Ch_1_Glob == 'A';
Bool_Glob = Bool_Loc | Bool_Glob;
Ch_2_Glob = 'B';
}
void Proc_5() {
Ch_1_Glob = 'A';
Bool_Glob = 0 ;
}
void Proc_6(int Enum_Val_Par, int Enum_Ref_Par) {
Enum_Ref_Par = Enum_Val_Par;
if (!Func_3(Enum_Val_Par))
Enum_Ref_Par = Ident_4;
switch (Enum_Val_Par) {
case Ident_1:
Enum_Ref_Par = Ident_1;
break;
case Ident_2:
if (Int_Glob > 100)
Enum_Ref_Par = Ident_1;
else
Enum_Ref_Par = Ident_4;
break;
case Ident_3:
Enum_Ref_Par = Ident_2;
break;
case Ident_4:
break;
case Ident_5:
Enum_Ref_Par = Ident_3;
break;
}
}
void Proc_7(int Int_1_Par_Val, int Int_2_Par_Val, int Int_Par_Ref) {
int Int_Loc;
Int_Loc = Int_1_Par_Val + 2;
Int_Par_Ref = Int_2_Par_Val + Int_Loc;
}
void Proc_8 (mixed *Arr_1_Par_Ref, mixed *Arr_2_Par_Ref,
int Int_1_Par_Val, int Int_2_Par_Val) {
int Int_Index, Int_Loc;
Int_Loc = Int_1_Par_Val + 5;
Arr_1_Par_Ref[Int_Loc] = Int_2_Par_Val;
Arr_1_Par_Ref[Int_Loc + 1] = Arr_1_Par_Ref[Int_Loc];
Arr_1_Par_Ref[Int_Loc + 30] = Int_Loc;
for (Int_Index = Int_Loc; Int_Index <= Int_Loc + 1; ++Int_Index)
Arr_2_Par_Ref[Int_Loc][Int_Index] = Int_Loc;
Arr_2_Par_Ref[Int_Loc][Int_Loc - 1] += 1;
Arr_2_Par_Ref[Int_Loc + 20][Int_Loc] = Arr_1_Par_Ref[Int_Loc];
Int_Glob = 5;
}
int Func_1(int Ch_1_Par_Val, int Ch_2_Par_Val) {
int Ch_1_Loc, Ch_2_Loc;
Ch_1_Loc = Ch_1_Par_Val;
Ch_2_Loc = Ch_1_Loc;
if (Ch_2_Loc != Ch_2_Par_Val)
return Ident_1;
else {
Ch_1_Glob = Ch_1_Loc;
return Ident_2;
}
}
int Func_2(string Str_1_Par_Ref, string Str_2_Par_Ref) {
int Int_Loc, Ch_Loc;
Int_Loc = 2;
while (Int_Loc <= 2)
if (Func_1(Str_1_Par_Ref[Int_Loc], Str_2_Par_Ref[Int_Loc + 1]) == Ident_1) {
Ch_Loc = 'A';
Int_Loc += 1;
}
if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
Int_Loc = 7;
if (Ch_Loc == 'R')
return 1;
else {
if (Str_1_Par_Ref > Str_2_Par_Ref) {
Int_Loc += 7;
Int_Glob = Int_Loc;
return 1;
} else
return 0;
}
}
int Func_3(int Enum_Par_Val) {
int Enum_Loc;
Enum_Loc = Enum_Par_Val;
if (Enum_Loc == Ident_3)
return 1;
else
return 0;
}

381
mudlib/dhrystone2.c Normal file
View File

@ -0,0 +1,381 @@
//===========================================================================
// Dhrystone-2.1 Benchmark for LPC
//
// Don't take this too serious :-) Sven C. Dack
//
// Compared to the original LPC dhrystone, this one has been modified
// to make less indirect data accesses in order to bring it more in
// line with Python's pystone.
//===========================================================================
#define Default_Number_Of_Runs 1000
#pragma strong_types
//===========================================================================
// Support functions to simulate memory allocation and other stuff..
mixed *alloc_array_50() { return allocate(50); }
mixed *alloc_array_50_50() {
mixed *arr;
int i;
for (i = 50, arr = allocate(50); i--; arr[i] = allocate(50));
return arr;
}
mixed * alloc_record() {
#define M_PTR_COMP 0
#define M_DISCR 1
#define M_ENUM_COMP 2
#define M_INT_COMP 3
#define M_STR_COMP 4
#define M_LENGTH 5
return ({ /* M_PTR_COMP */ 0
, /* M_DISCR */ 0
, /* M_ENUM_COMP */ 0
, /* M_INT_COMP */ 0
, /* M_STR_COMP */ ""
});
}
mixed * copy_record(mixed * rec) {
mixed * r;
return copy(rec);
}
int times() {
int *ru;
ru = rusage();
return ru[0] + ru[1];
}
//===========================================================================
// The global variables.
#define Ident_1 0
#define Ident_2 1
#define Ident_3 2
#define Ident_4 3
#define Ident_5 4
#define Enum_Comp 0
#define Int_Comp 1
#define Str_Comp 2
mixed * Ptr_Glob, Next_Ptr_Glob;
int Int_Glob;
int Bool_Glob;
int Ch_1_Glob, Ch_2_Glob;
mixed *Arr_1_Glob;
mixed *Arr_2_Glob;
int Begin_Time, End_Time, User_Time;
float Milliseconds, Dhrystones_Per_Second;
//===========================================================================
// Prototypes all functions (including those defined later).
void Proc_1(mixed * m1);
int Proc_2(int i1);
mixed * Proc_3(mixed * m1);
void Proc_4();
void Proc_5();
int Proc_6(int i1);
int Proc_7(int i1, int i2);
void Proc_8(mixed *a1, mixed *a2, int i1, int i2);
int Func_1(int i1, int i2);
int Func_2(string s1, string s2);
int Func_3(int i1);
//===========================================================================
float main(int Number_Of_Runs, int silent) {
int Int_1_Loc, Int_2_Loc, Int_3_Loc;
int Ch_Index;
int Enum_Loc;
string Str_1_Loc, Str_2_Loc;
int Run_Index;
if (Number_Of_Runs <= 0)
Number_Of_Runs = Default_Number_Of_Runs;
Arr_1_Glob = alloc_array_50();
Arr_2_Glob = alloc_array_50_50();
Str_1_Loc = "";
Str_2_Loc = "";
Next_Ptr_Glob = alloc_record();
Ptr_Glob = alloc_record();
Ptr_Glob[M_PTR_COMP] = Next_Ptr_Glob;
Ptr_Glob[M_DISCR] = Ident_1;
Ptr_Glob[M_ENUM_COMP] = Ident_3;
Ptr_Glob[M_INT_COMP] = 40;
Ptr_Glob[M_STR_COMP] = "DHRYSTONE PROGRAM, SOME STRING";
Str_1_Loc = "DHRYSTONE PROGRAM, 1'ST STRING";
Arr_2_Glob[8][7] = 10;
if (!silent) {
write("Dhrystone Benchmark, Version 2.1 (Language: LPC)\n");
write("Execution starts, " + Number_Of_Runs + " runs through Dhrystone\n");
}
Begin_Time = times();
for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) {
Proc_5();
Proc_4();
Int_1_Loc = 2;
Int_2_Loc = 3;
Str_2_Loc = "DHRYSTONE PROGRAM, 2'ND STRING";
Enum_Loc = Ident_2;
Bool_Glob = !Func_2(Str_1_Loc, Str_2_Loc);
while (Int_1_Loc < Int_2_Loc) {
Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
Int_3_Loc = Proc_7(Int_1_Loc, Int_2_Loc);
Int_1_Loc += 1;
}
Proc_8(Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
Proc_1(Ptr_Glob);
for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) {
if (Enum_Loc == Func_1(Ch_Index, 'C')) {
Enum_Loc = Proc_6(Ident_1);
//Str_2_Loc = "DHRYSTONE PROGRAM, 3'RD STRING";
//Int_2_Loc = Run_Index;
//Int_Glob = Run_Index;
}
}
Int_2_Loc = Int_2_Loc * Int_1_Loc;
Int_1_Loc = Int_2_Loc / Int_3_Loc;
Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
Int_1_Loc = Proc_2(Int_1_Loc);
}
End_Time = times();
if (!silent)
{
write("Execution ends.\n");
write("Final values of the variables used in the benchmark:\n\n");
printf("Int_Glob: %d\n", Int_Glob);
printf(" should be: %d\n", 5);
printf("Bool_Glob: %d\n", Bool_Glob);
printf(" should be: %d\n", 1);
printf("Ch_1_Glob: %c\n", Ch_1_Glob);
printf(" should be: %c\n", 'A');
printf("Ch_2_Glob: %c\n", Ch_2_Glob);
printf(" should be: %c\n", 'B');
printf("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
printf(" should be: %d\n", 7);
printf("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
printf(" should be: Number_Of_Runs + 10\n");
#if 0
printf("Ptr_Glob->\n");
printf(" Ptr_Comp: %O\n", Ptr_Glob[M_PTR_COMP]);
printf(" should be: (implementation-dependent)\n");
#endif
printf(" Discr: %d\n", Ptr_Glob[M_DISCR]);
printf(" should be: %d\n", 0);
printf(" Enum_Comp: %d\n", Ptr_Glob[M_ENUM_COMP]);
printf(" should be: %d\n", 2);
printf(" Int_Comp: %d\n", Ptr_Glob[M_INT_COMP]);
printf(" should be: %d\n", 17);
printf(" Str_Comp: %s\n", Ptr_Glob[M_STR_COMP]);
printf(" should be: DHRYSTONE PROGRAM, SOME STRING\n");
#if 0
printf("Next_Ptr_Glob->\n");
printf(" Ptr_Comp: %O\n", Next_Ptr_Glob[M_PTR_COMP]);
printf(" should be: (implementation-dependent), same as above\n");
#endif
printf(" Discr: %d\n", Next_Ptr_Glob[M_DISCR]);
printf(" should be: %d\n", 0);
printf(" Enum_Comp: %d\n", Next_Ptr_Glob[M_ENUM_COMP]);
printf(" should be: %d\n", 1);
printf(" Int_Comp: %d\n", Next_Ptr_Glob[M_INT_COMP]);
printf(" should be: %d\n", 18);
printf(" Str_Comp: %s\n", Next_Ptr_Glob[M_STR_COMP]);
printf(" should be: DHRYSTONE PROGRAM, SOME STRING\n");
printf("Int_1_Loc: %d\n", Int_1_Loc);
printf(" should be: %d\n", 5);
printf("Int_2_Loc: %d\n", Int_2_Loc);
printf(" should be: %d\n", 13);
printf("Int_3_Loc: %d\n", Int_3_Loc);
printf(" should be: %d\n", 7);
printf("Enum_Loc: %d\n", Enum_Loc);
printf(" should be: %d\n", 1);
printf("Str_1_Loc: %s\n", Str_1_Loc);
printf(" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
printf("Str_2_Loc: %s\n", Str_2_Loc);
printf(" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
printf("\n");
}
User_Time = End_Time - Begin_Time;
if (User_Time <= 0) {
if (!silent) {
printf("Your rusage() doesn't seem to work: User_Time is %d.\n", User_Time);
write("\n");
}
} else if (User_Time < (2*100)) {
if (!silent) {
write("Measured time too small to obtain meaningful results\n");
write("Please increase number of runs\n");
write("\n");
}
} else {
Milliseconds = to_float(User_Time) / Number_Of_Runs;
Dhrystones_Per_Second = 1000.0 * Number_Of_Runs / User_Time;
if (!silent)
{
printf ("Milliseconds for one run through Dhrystone: ");
printf ("%6.1f \n", Milliseconds);
printf ("Dhrystones per Second: ");
printf ("%6.1f \n", Dhrystones_Per_Second);
}
}
return Dhrystones_Per_Second;
}
void Proc_1(mixed * Ptr_Val_Par) {
mixed * Next_Record;
Next_Record = Ptr_Val_Par[M_PTR_COMP];
Ptr_Val_Par[M_PTR_COMP] = copy_record(Ptr_Glob);
Ptr_Val_Par[M_INT_COMP] = 5;
Next_Record[M_STR_COMP] = Ptr_Val_Par[M_STR_COMP];
Next_Record[M_INT_COMP] = Ptr_Val_Par[M_INT_COMP];
Next_Record[M_PTR_COMP] = Ptr_Val_Par[M_PTR_COMP];
Next_Record[M_PTR_COMP] = Proc_3(Next_Record[M_PTR_COMP]);
if (Next_Record[M_DISCR] == Ident_1) {
Next_Record[M_INT_COMP] = 6;
Next_Record[M_ENUM_COMP] = Proc_6(Ptr_Val_Par[M_ENUM_COMP]);
Next_Record[M_PTR_COMP] = Ptr_Glob[M_PTR_COMP];
Next_Record[M_INT_COMP] = Proc_7( Next_Record[M_INT_COMP], 10);
} else
Ptr_Val_Par = copy_record(Ptr_Val_Par[M_PTR_COMP]);
}
int Proc_2(int Int_Par) {
int Int_Loc, Enum_Loc;
Int_Loc = Int_Par + 10;
do
if (Ch_1_Glob == 'A') {
Int_Loc -= 1;
Int_Par = Int_Loc - Int_Glob;
Enum_Loc = Ident_1;
}
while (Enum_Loc != Ident_1);
return Int_Par;
}
mixed * Proc_3(mixed * Ptr_Ref_Par) {
if (Ptr_Glob != 0)
Ptr_Ref_Par = Ptr_Glob[M_PTR_COMP];
Ptr_Glob[M_INT_COMP] = Proc_7(10, Int_Glob);
return Ptr_Ref_Par;
}
void Proc_4() {
int Bool_Loc;
Bool_Loc = Ch_1_Glob == 'A';
Bool_Glob = Bool_Loc | Bool_Glob;
Ch_2_Glob = 'B';
}
void Proc_5() {
Ch_1_Glob = 'A';
Bool_Glob = 0 ;
}
int Proc_6(int Enum_Val_Par) {
int Enum_Par_Out;
Enum_Par_Out = Enum_Val_Par;
if (!Func_3(Enum_Val_Par))
Enum_Par_Out = Ident_4;
switch (Enum_Val_Par) {
case Ident_1:
Enum_Par_Out = Ident_1;
break;
case Ident_2:
if (Int_Glob > 100)
Enum_Par_Out = Ident_1;
else
Enum_Par_Out = Ident_4;
break;
case Ident_3:
Enum_Par_Out = Ident_2;
break;
case Ident_4:
break;
case Ident_5:
Enum_Par_Out = Ident_3;
break;
}
return Enum_Par_Out;
}
int Proc_7(int Int_1_Par_Val, int Int_2_Par_Val) {
int Int_Loc;
Int_Loc = Int_1_Par_Val + 2;
return Int_2_Par_Val + Int_Loc;
}
void Proc_8 (mixed *Arr_1_Par_Ref, mixed *Arr_2_Par_Ref,
int Int_1_Par_Val, int Int_2_Par_Val) {
int Int_Index, Int_Loc;
Int_Loc = Int_1_Par_Val + 5;
Arr_1_Par_Ref[Int_Loc] = Int_2_Par_Val;
Arr_1_Par_Ref[Int_Loc + 1] = Arr_1_Par_Ref[Int_Loc];
Arr_1_Par_Ref[Int_Loc + 30] = Int_Loc;
for (Int_Index = Int_Loc; Int_Index <= Int_Loc + 1; ++Int_Index)
Arr_2_Par_Ref[Int_Loc][Int_Index] = Int_Loc;
Arr_2_Par_Ref[Int_Loc][Int_Loc - 1] += 1;
Arr_2_Par_Ref[Int_Loc + 20][Int_Loc] = Arr_1_Par_Ref[Int_Loc];
Int_Glob = 5;
}
int Func_1(int Ch_1_Par_Val, int Ch_2_Par_Val) {
int Ch_1_Loc, Ch_2_Loc;
Ch_1_Loc = Ch_1_Par_Val;
Ch_2_Loc = Ch_1_Loc;
if (Ch_2_Loc != Ch_2_Par_Val)
return Ident_1;
else {
Ch_1_Glob = Ch_1_Loc;
return Ident_2;
}
}
int Func_2(string Str_1_Par_Ref, string Str_2_Par_Ref) {
int Int_Loc, Ch_Loc;
Int_Loc = 2;
while (Int_Loc <= 2)
if (Func_1(Str_1_Par_Ref[Int_Loc], Str_2_Par_Ref[Int_Loc + 1]) == Ident_1) {
Ch_Loc = 'A';
Int_Loc += 1;
}
if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
Int_Loc = 7;
if (Ch_Loc == 'R')
return 1;
else {
if (Str_1_Par_Ref > Str_2_Par_Ref) {
Int_Loc += 7;
Int_Glob = Int_Loc;
return 1;
} else
return 0;
}
}
int Func_3(int Enum_Par_Val) {
int Enum_Loc;
Enum_Loc = Enum_Par_Val;
if (Enum_Loc == Ident_3)
return 1;
else
return 0;
}

112
mudlib/dns_resolve.c Normal file
View File

@ -0,0 +1,112 @@
void
dns_resolve (string hostname, closure callback)
// Try to lookup the IP for the fully qualified <hostname> using direct ERQ
// communication. Once the name is resolved, call callback() with the
// resolved name as parameter.
//
// Note: If the ERQ is unavailable, callback() is called with the original
// hostname.
//
// preferably to be installed as "simul efun." latest version available
// in world/net/library.i of psycMUVE (download from http://muve.pages.de)
// this version runs with broken and fixed erq's alike.
//
// Written by Tobias@Heldensaga and Arne@Elridion.
{
closure c;
if (sscanf(hostname,"%~D.%~D.%~D.%~D") == 4) {
// hostname is an IP already. Just call the callback.
funcall(callback, hostname);
return;
}
c = lambda( ({ 'name }), ({
(#'switch), ({ #'sizeof, 'name }),
({ 4 }), // ERQ: name resolved!
({ (#',),
({ (#'=),'name,({ (#'map),'name,#'&,255 }) }),
({ (#'=),'name,
({
(#'sprintf),"%d.%d.%d.%d",
({ #'[, 'name, 0 }),
({ #'[, 'name, 1 }),
({ #'[, 'name, 2 }),
({ #'[, 'name, 3 })
})
}),
({ (#'funcall), callback, 'name })
}),
(#'break),
({ 6 + strlen(hostname) }), // XERQ
({ (#',),
({ (#'=),'name,({ (#'map),'name,#'&,255 }) }),
({ (#'=),'name,
({
(#'sprintf),"%d.%d.%d.%d",
({ #'[, 'name, 1
}),
({ #'[, 'name, 2
}),
({ #'[, 'name, 3
}),
({ #'[, 'name, 4 })
})
}),
({ (#'funcall), callback, 'name })
}),
(#'break),
({ #'default }),
({
#'debug_message, "FATAL: ERQ could not resolve \""
+ hostname + "\". The callback will not be called.\n"
}),
(#'break)
})
);
#ifdef THEDAYWEARESURENOONERUNSABUGGYERQ
if (!send_erq(ERQ_LOOKUP, hostname, c))
#else
// appending the zero byte fixes a bug in erq. sick!
if (!send_erq(ERQ_LOOKUP, to_array(hostname) + ({ 0 }), c))
#endif
{
// if we cannot resolve using erq, we'll send back the hostname,
// so the driver can do a blocking resolve itself (needed for
// net_connect())
funcall(callback, hostname);
}
}
#if 0
/*------------------------------------------------------------------------*/
// typical usage example taken from PSYCmuve world/net/irc/gatebot.c
// this ensures a non-blocking connect to a remote service even by name.
//
connect(host, port) {
unless (host) host = IRCNET_HOST;
unless (port) port = IRCNET_PORT;
D2( D("IRCgate resolving hostname "+ host +"\n"); )
dns_resolve(host, lambda(({ 'result }),
({ #'connect2, 'result, port })));
}
connect2(host, port) {
#if __EFUN_DEFINED__(net_connect)
int res;
D0( D(S("IRCgate attempting connect to %O:%O\n", host, port)); )
res = net_connect(host, port);
if (res) monitor_report("_failure_network_connect_call",
"ircbot: connect to "+host+" returns "+ res);
return res;
#else
D2( D("IRCgate * Oh, driver does not provide net_connect()\n"); )
return -9;
#endif
}
#endif /* EXAMPLE */

214
mudlib/erq-tool.c Normal file
View File

@ -0,0 +1,214 @@
#include <erq.h>
object command_giver;
int *ticket;
int verbose = 1;
short() {
return "Erq tool";
}
id(s) {
switch(s) {
case "erq-tool":
case "erq tool":
case "erq":
return 1;
default:
return 0;
}
}
long() {
return "\
This tool allows you to use the ERQ_SPAWN / ERQ_SEND / ERQ_KILL requests\n\
of the external command demon.\n\
\n\
Usage:\n\
e <program> <arguments>\n\
start <program> with <arguments>. Blanks, tabs and backslashes have to be\n\
quoted if desired as a part of the program name and / or an argument.\n\
The text is directly sent to the ERQ_SPAWN request, which does the\n\
commandline interpretation wrt. blanks and whitespace.\n\
You can only start a new program with this tool while it is not\n\
currently controlling another one.\n\
e <text>\n\
send <text> to the standard input of the running program.\n\
er\n\
send a single newline to the standard input of the running program.\n\
ekill\n\
kill the running program\n\
ekill <signal>\n\
send <signal> to the running program.\n\
everbose\n\
toggle verbose mode.\n\
econnect\n\
send all input to stdin of the running program.\n\
\n\
output from stdout will be displayed with a prepended single quote,\n\
output from stderr will be displayed with a prepended double quote.\n\
";
}
get() {
return 1;
}
drop(silently) {
return query_verb() != "give";
}
init() {
add_action("erq", "e");
add_action("erq", "er");
add_action("ekill", "ekill");
add_action("everbose", "everbose");
add_action("econnect", "econnect");
}
receive_output(a) {
if (!ticket) {
switch(a[0]) {
case ERQ_OK:
write("Command accepted.\n");
ticket = a[1..];
return;
case ERQ_E_ARGLENGTH:
write("Too long argument\n");
break;
case ERQ_E_ARGNUMBER:
write("Too many arguments\n");
break;
case ERQ_E_PATHLEN:
write("Too long pathname\n");
break;
case ERQ_E_ARGFORMAT:
write("Syntax error\n");
break;
case ERQ_E_ILLEGAL:
write("Illegal pathname\n");
break;
case ERQ_E_FORKFAIL:
write("Fork failed\n");
break;
default:
write("Unknown error, command rejected\n");
break;
}
command_giver = 0;
return;
}
switch(a[0]) {
case ERQ_STDOUT:
a[0] = '\'';
tell_object(command_giver, to_string(a));
return;
case ERQ_STDERR:
a[0] = '\"';
tell_object(command_giver, to_string(a));
return;
case ERQ_EXITED:
tell_object(command_giver,
sprintf("Program exited with status %d.\n", a[1]));
break;
case ERQ_SIGNALED:
tell_object(command_giver,
sprintf("Program caught signal %d.\n", a[1]));
break;
case ERQ_E_UNKNOWN:
tell_object(command_giver, "Unknown error.\n");
break;
}
command_giver = 0;
ticket = 0;
}
send_reply(a, p, s) {
switch (a[0]) {
case ERQ_OK:
if (verbose)
tell_object(p, "Ok.\n");
break;
default:
tell_object(p, "Input not fully accepted.\n");
break;
}
}
kill_reply(a, p, s) {
switch (a[0]) {
case ERQ_OK:
if (verbose)
tell_object(p, "Ok.\n");
break;
case ERQ_E_TICKET:
tell_object(p, "Trying to kill a dead process\n");
break;
case ERQ_E_ILLEGAL:
tell_object(p, "Illegal signal\n");
break;
default:
tell_object(p, "Kill error.\n");
break;
}
}
erq(s) {
if (!s)
s = "";
if (ticket) {
send_erq(ERQ_SEND, ticket+to_array(s)+({'\n'}), lambda(({'a}),
({#'send_reply, 'a, command_giver, s})));
return 1;
} else if (!command_giver) {
command_giver = this_player();
send_erq(ERQ_SPAWN, s, #'receive_output);
return 1;
} else {
write("Waiting for command to be accepted\n");
return 1;
}
}
ekill(s) {
int signal;
if (!ticket) {
write("No program running\n");
return 1;
}
if ( !(s && sscanf(s, "%d", signal)) )
signal = 9;
send_erq(ERQ_KILL, ticket+({0,0,0,signal}), lambda(({'a}),
({#'kill_reply, 'a, command_giver, signal})));
return 1;
}
everbose(s) {
switch(s) {
case "on":
verbose = 1;
return 1;
case "off":
verbose = 0;
return 1;
case 0:
verbose = !verbose;
return 1;
}
}
econnect() {
write("Use 'edisconnect' to stop.\n");
add_action("erq", "", 2);
add_action("edisconnect", "edisconnect");
add_action("erq", "er");
return 1;
}
edisconnect() {
remove_action("");
remove_action("edisconnect");
remove_action("er");
return 1;
}

1255
mudlib/master_skeleton.c Normal file

File diff suppressed because it is too large Load Diff

171
mudlib/pgsql.c Normal file
View File

@ -0,0 +1,171 @@
// Example object for the use of PostgreSQL efuns.
inherit "/i/item";
inherit "/i/move";
#define TP(x) player->tell(x)
//#define TP(x) this_player()->tell(x)
#include <input_to.h>
#include <pgsql.h>
#include <lpctypes.h>
int connected = 0;
object player;
string *keyvalues(mapping m, string key) {
string *ret = ({});
int i, rows = widthof(m);
for (i = 0; i < rows; i++) {
ret += ({ m[key,i] });
}
return ret;
}
string *prettytable (mixed res) {
int rows, cols, i, j, total, tmp;
string row;
string *ret, *fnames, line, *fsizes;
ret = ({});
fsizes = ({});
cols = sizeof(res);
if (typeof(res) == T_POINTER) {
for (i = 0; i < cols; i++)
ret += ({ implode(res[i], ",") });
return ret;
}
fnames = m_indices(res);
rows = widthof(res);
for (i = 0; i < cols; i++) {
tmp = max(map(keyvalues(res, fnames[i])+({ fnames[i] }), #'sizeof));
total += tmp;
fsizes += ({ to_string(tmp) });
}
total += sizeof(fsizes)*3 + 1;
ret += ({ sprintf(" +%"+to_string(total-2)+"'-'s+", "") });
line = " | ";
for (j = 0; j < cols; j++) {
line += sprintf("%|"+fsizes[j]+"."+fsizes[j]+"s | ", fnames[j]);
}
ret += ({ line });
ret += ({ ret[0] });
for (i = 0; i < rows; i++) {
line = " | ";
for (j = 0; j < cols; j++) {
line += sprintf("%-"+fsizes[j]+"."+fsizes[j]+"s | ",
res[fnames[j],i]);
}
ret += ({ line });
}
ret += ({ ret[0] });
return ret;
}
int result (int nr, mixed res, int id) {
string *table;
TP("\n");
switch (nr) {
case PGRES_COMMAND_OK:
TP(res+"\n");
break;
case PGRES_TUPLES_OK:
if (res) {
table = prettytable(res);
table += ({ "Rows: "+to_string(widthof(res))+"\n" });
TP(implode(table, "\n"));
} else {
TP("No rows matched.\n");
}
break;
case PGRES_BAD_RESPONSE:
case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR:
TP(res);
break;
case PGRES_NOTICE:
TP(res);
break;
case PGCONN_SUCCESS:
TP("PG-connection established.\n");
connected = 1;
break;
case PGCONN_FAILED:
TP("PG-connection failed: "+res+"\n");
connected = 0;
break;
case PGCONN_ABORTED:
TP("PG-connection lost: "+res+"\n");
connected = 0;
break;
}
if (connected)
tell_object(player, "SQL> ");
else
tell_object(player, "sql> ");
}
int _sql (string str) {
string prompt;
if (str && !connected && (lower_case(str[0..6]) == "connect")) {
str = str[8..];
if (pg_connect(str, "result") < 0)
TP("Error in connect-string");
else
TP("Connecting...");
} else if (str && connected && (lower_case(str) == "disconnect")) {
pg_close();
connected = 0;
TP("Disconnected...");
} else if (str && ((lower_case(str) == "exit") || (lower_case(str) == "quit")))
return 1;
else if (str && strlen(str)) {
if (!connected)
TP("Connect first, brainy\n");
else
pg_query(str, RESULT_ASSOC);
}
if (connected)
prompt = "SQL> ";
else
prompt = "sql> ";
input_to("_sql", INPUT_PROMPT, prompt);
return 1;
}
int sql (string str) {
TP("SQL-Shell v0.1a");
TP("===============");
TP("Commands: connect, disconnect, exit, quit");
TP("Everything else is treated as SQL-command");
TP("");
_sql(str);
return 1;
}
void init (void) {
::init();
player = this_player();
if (playerp(environment()))
add_action("sql", "sql");
}
void create (void) {
::create();
set_name("sqlshell");
set_id(({"sqlshell","sql"}));
set_long("Eine SQL-Shell");
set_gender("w");
}

108
mudlib/psyc-tls.c Normal file
View File

@ -0,0 +1,108 @@
#include <net.h> // vim syntax=lpc
/* Wrapper for using the tls_check_certificate() efun.
*
* If for example the efun returns this raw data:
* ({
* 0,
* ({
* "2.5.4.3",
* "commonName",
* "goodadvice.pages.de"
* }),
* ({
* 0,
* 0,
* 0,
* 0,
* 0,
* 0,
* 0,
* 0,
* 0,
* 0,
* 0,
* 0,
* "2.5.29.17",
* "X509v3 Subject Alternative Name",
* ({
* "dNSName",
* "dNSName",
* "goodadvice.pages.de",
* "1.3.6.1.5.5.7.8.5",
* "1.3.6.1.5.5.7.8.5",
* "goodadvice.pages.de"
* })
* })
* })
*
* the wrapper will transform it into:
* ([
* 0: 0
* "2.5.29.17:dNSName": "goodadvice.pages.de",
* "2.5.4.3": "goodadvice.pages.de",
* "2.5.29.17:1.3.6.1.5.5.7.8.5": "goodadvice.pages.de",
* ])*
*/
mapping tls_certificate(object who, int longnames) {
mixed *extra, extensions;
mapping cert;
int i, j;
cert = ([ ]);
#if __EFUN_DEFINED__(tls_check_certificate)
# ifdef WANT_S2S_SASL
extra = tls_check_certificate(who, 1);
unless (extra) return 0;
cert[0] = extra[0];
extensions = extra[2];
extra = extra[1];
for (i = 0; i < sizeof(extra); i += 3) {
mixed t;
t = cert[extra[i]];
unless (t) {
cert[extra[i]] = extra[i+2];
} else if (stringp(t)) {
cert[extra[i]] = ({ t, extra[i+2] });
} else if (pointerp(t)) {
cert[extra[i]] += ({ extra[i+2] });
} else {
// should not happen
}
}
if (longnames) {
// set up short/long names
for (i = 0; i < sizeof(extra); i +=3) {
cert[extra[i+1]] = cert[extra[i]];
}
}
for (i = 0; i < sizeof(extensions); i += 3) {
string key, mkey;
mixed *val;
unless(extensions[i]) continue;
key = extensions[i];
val = extensions[i+2];
for (j = 0; j < sizeof(val); j += 3) {
mixed t;
mkey = key + ":" + val[j];
t = cert[mkey];
unless (t) {
cert[mkey] = val[j+2];
} else if (stringp(t)) {
cert[mkey] = ({ t, val[j+2] });
} else if (pointerp(t)) {
cert[mkey] += ({ val[j+2] });
} else {
// should not happen
}
}
}
# endif
#endif
return cert;
}

40
mudlib/query_ip_name.c Normal file
View File

@ -0,0 +1,40 @@
/* IPv4/IPv6 name lookup using ERQ
* by Fini <ujastrow@mail.desy.de>
* Tue, 9 Mar 2004 08:20:16 +0100 (MET)
*/
void get_ip_name(string ip_num) {
[...]
num=allocate(4);
if (sscanf(ip_num, "%d.%d.%d.%d", num[0], num[1], num[2], num[3])!=4)
continue;
# ifdef RDNS_DEBUG
log_file("IP-NAME",
sprintf(" ** RDNS request for IPv4 %s sent\n", ip_num));
# endif
send_erq(ERQ_RLOOKUP, num, #'_got_ipv4_name);
[...]
}
void _got_ipv4_name(int* data, int len) {
int* x;
string ip_num, ip_nam;
if (previous_object()) return; // only the driver may call this
if (!pointerp(data) || len<5) return;
x=allocate(4);
if ((x[0]=data[0])<0) x[0]+=256; // not needed with newer drivers
if ((x[1]=data[1])<0) x[1]+=256;
if ((x[2]=data[2])<0) x[2]+=256;
if ((x[3]=data[3])<0) x[3]+=256;
ip_num=sprintf("%d.%d.%d.%d", x[0], x[1], x[2], x[3]);
ip_nam=to_string(data[4..]);
# ifdef RDNS_DEBUG
log_file("IP-NAME", sprintf("got v4: %s -> %s\n", ip_num, ip_nam));
# endif
if (ip_num==ip_nam) return; // not resolved
if (!ip_map) ip_map=get_extra_wizinfo(0)[IP_NAMES];
ip_map[ip_num, 0]=ip_nam;
ip_map[ip_num, 1]=time();
}

449
mudlib/simul_efun-dr.c Normal file
View File

@ -0,0 +1,449 @@
/* This is an addition to the simul_efun file for a fast migration from
* the -DR parser. Only the ls() function of the original simul_efun need to
* be commented out
*/
#include "/sys/lpctypes.h"
#define ATTRIBUTE_INDEX 2
#define TEXT_WIDTH 70
/*
* check_ref() is only a fake function.
* missing: query_arg/this_arg(), remove_action()
*
* The following defines might be appropriate when you need to stay with
* old code and want speed. Put them in an appropriate header file or in
* the auto_include string.
*
* #define caller() previous_object()
* if using OLD_PREVIOUS_OBJECT_BEHAVIOUR :
* #define caller() previous_object(0) // always works, but slower
*
* #define contents(ob) all_inventory((ob))
* #define deletem(m, d) efun::m_delete((m), (d))
* #define this_verb() query_verb()
* #define atoi(str) to_int(str)
* #define keys(m) m_indices(m)
* #define mapp(m) mappingp(m)
*
* The following defines have a problem: a parameter is used twice.
* #define deletea(a, start, end) ((a)[0..(start)-1] + (a)[(end)+1..])
* #define index(a, d, start) member((start) ? (a)[(start)..] : (a) , (d))
* #define searcha(a, d, start) member((start) ? (a)[(start)..] : (a) , (d))
*/
static void start_simul_efun_dr() {
mixed *info;
info = get_extra_wizinfo(0);
if (!info[ATTRIBUTE_INDEX])
info[ATTRIBUTE_INDEX] = allocate_mapping(0, 1);
if (find_call_out("clean_simul_efun_dr") < 0)
call_out("clean_simul_efun_dr", 900);
}
static void clean_simul_efun_dr() {
/* There might be destructed objects as keys. */
m_indices(get_extra_wizinfo(0)[ATTRIBUTE_INDEX]);
remove_call_out("clean_simul_efun_dr");
call_out("clean_simul_efun_dr", 3600);
}
varargs void add_attribute(string name, mixed value, object ob) {
mapping attributes;
if (!ob) {
if (objectp(value)) {
ob = value;
value = 1;
} else {
ob = previous_object();
}
}
attributes =
(attributes = get_extra_wizinfo(0)[ATTRIBUTE_INDEX])[ob] ||
(attributes[ob] = allocate_mapping(1, 1));
if (member(attributes, quote(name))) {
attributes[quote(name)] = value;
return;
}
attributes[name] = value;
}
varargs void add_prot_attribute(string name, mixed value, object ob) {
mapping attributes;
if (!ob) {
if (objectp(value)) {
ob = value;
value = 1;
} else {
ob = previous_object();
}
}
efun::m_delete(
( (attributes = get_extra_wizinfo(0)[ATTRIBUTE_INDEX])[ob] ||
(attributes[ob] = allocate_mapping(1, 1)) )
, name)[quote(name)] = value;
}
#ifndef caller
object caller() {
return previous_object(1);
}
#endif /* caller */
/* int */ mixed check_ref() {
/* There are other ways to debug ref counts. Although a simul_efun is
* possible, I doubt that it would be worth the trouble
*/
return 42.42;
}
object *contents(object ob) {
return all_inventory(ob);
}
varargs void delete_attribute(string name, object ob) {
mapping attributes;
if (attributes =
get_extra_wizinfo(0)[ATTRIBUTE_INDEX][ob || previous_object()])
{
if (member(attributes, quote(name)))
raise_error(
sprintf("Error, cannot delete protected attribute %s.\n", name));
if ( !sizeof(efun::m_delete(attributes, name)) )
efun::m_delete(
get_extra_wizinfo(0)[ATTRIBUTE_INDEX],
ob || previous_object()
);
}
}
varargs mixed deletea(mixed a, int start, int end)
{
if (!end) /* This isn't really exact; it should */
end = start; /* only be done if end is not given. */
if (end == sizeof(a) - 1) /* Avoid "out of bounds" . */
return a[0..start - 1];
return a[0..start-1] + a[end+1..];
}
mapping deletem(mapping m, mixed d) {
return efun::m_delete(m, d);
}
void dumpobjs(int start, int end) {
object ob;
rm("/OBJDUMP");
if (end <= 0) {
printf("Dumping all objects starting with %d.\n", start);
end = 0x7fffffff;
} else {
printf("Dumping objects %d through %d.\n", start, end);
}
write_file("/OBJDUMP",
sprintf("Object Location\n"));
for (ob = debug_info(start); ob && start <= end;
ob = debug_info(2, ob), start++)
write_file("/OBJDUMP", sprintf("%-40s %s\n", file_name(ob),
(environment(ob)?file_name(environment(ob)):"None")));
write("Done.\n");
}
int exists(string file) {
return file_size(file) != -1;
}
string *files(string path) {
mixed *a;
string *b;
int i, j;
set_this_object(previous_object());
a = get_dir(path, 3);
/* Don't call this locally, unless you add code to set this_object() back */
b = allocate(j = (i = sizeof(a)) >> 1);
while (i)
b[--j] = a[--i] < 0 ? a[--i] + "/" : a[--i];
return b;
}
string format(string text, int width) {
if (width < 0)
raise_error("Bad width given to format(); must be >= 0.\n");
return sprintf("%*-=s", width || TEXT_WIDTH, text);
}
varargs mixed get_attribute(mixed m, object ob) {
mapping attributes;
if (!stringp(m))
return
transpose_array( ({
m_indices(
attributes =
get_extra_wizinfo(0)
[ATTRIBUTE_INDEX][m || previous_object()] ||
allocate_mapping(0,1)),
m_values(attributes)
}) ) ;
if ( ( attributes =
get_extra_wizinfo(0)[ATTRIBUTE_INDEX][ob || previous_object()]
) && (mapping_contains(&m, attributes, m) ||
mapping_contains(&m, attributes, quote(m)))
)
return m;
return -1;
}
varargs string *grab_file(string path, int start, int len) {
set_this_object(previous_object());
return explode(read_file(path, start, len), "\n");
/* Don't call this locally, unless you add code to set this_object() back */
}
int index(mixed a, mixed d, int start) {
return member(start ? a[start..] : a , d);
}
string pad(mixed str, int len, int padchar) {
string sp_format;
str = to_string(str);
if (len < 0) {
if (padchar) {
sp_format = "%' '*.*s";
sp_format[2] = padchar;
return sprintf(sp_format, -len, -len, str);
}
return sprintf("%*.*s", -len, -len, str);
}
if (padchar) {
sp_format = "%' '-*.*s%s";
sp_format[2] = padchar;
return sprintf(sp_format, len, len, str, "");
}
return sprintf("%-*.*s%s", len, len, str, "");
}
varargs void print(string text, int width) {
if (width > TEXT_WIDTH)
raise_error("Invalid size for argument 2 to print()\n");
if (width < 0)
raise_error("Bad width given to print(); must be >= 0.\n");
write(sprintf("%*-=s", width || TEXT_WIDTH, text));
}
varargs mixed query_attribute(string m, object ob) {
mapping attributes;
return
( attributes =
get_extra_wizinfo(0)[ATTRIBUTE_INDEX][ob || previous_object()]
) && (member(attributes, m) || member(attributes, quote(m)));
}
static int remote_command_flag;
int command(string str, object ob) {
/* Don't call this locally, unless you add code to set this_object() back */
int result;
object me;
if (!ob) {
set_this_object(previous_object());
return efun::command(str);
}
if (ob == previous_object()) {
set_this_object(previous_object());
return efun::command(str);
}
remote_command_flag++;
me = this_object();
set_this_object(previous_object());
result = efun::command(str, ob);
set_this_object(me);
remote_command_flag = 0; /* global variable... */
return result;
}
int remote_command() { return remote_command_flag; }
int root(object ob) {
return member(file_name(ob || previous_object()), '#') == -1;
}
int searcha(mixed a, mixed d, int start) {
return member(start ? a[start..] : a , d);
}
static private string *strsub_formats = ({0, "\\<%s\\B","\\B%s\\>","\\<%s\\>"});
string strsub(string input,string *patterns, int mode) {
int i;
string format;
if ( (i = sizeof(patterns)) & 1)
raise_error("Odd length array given to strsub.\n");
if (!mode) {
while (i) {
input = implode(explode(input, patterns[<i--]), patterns[<i--]);
}
return input;
}
format = strsub_formats[mode];
while (i) {
input =
implode(
regexplode(input, sprintf(format, patterns[<i--])),
patterns[<i--]
);
}
return input;
}
string this_verb() { return query_verb(); }
int atoi(string str) { return to_int(str); }
int cp(string from, string to) {
string str;
set_this_object(previous_object());
rm(to);
str = read_file(from);
write_file(to, str);
/* Don't call this locally, unless you add code to set this_object() back */
}
int in_editor(object ob) { return query_editing(ob) && 1; }
mixed *keys(mapping m) { return m_indices(m); }
int mapp(mixed m) { return mappingp(m); }
int memused() {
return rusage()[2];
}
object remove_shadow(object ob) {
if (!(ob))
if ( !(ob = previous_object()) )
return 0;
/* we are missing a test here to test for actual shadowing. */
funcall(bind_lambda(#'unshadow, ob || previous_object()));
return ob;
}
mixed *reallocate(mixed *a, int size) {
if (size > sizeof(a))
return a + allocate(size - sizeof(a));
return a[0..size-1];
}
string typeof(mixed m) {
switch(efun::typeof(m)) {
case T_OBJECT:
return "object";
case T_NUMBER:
return "int";
case T_POINTER:
return "vector";
case T_STRING:
return "string";
case T_MAPPING:
return "mapping";
default:
return "";
}
}
static int last_destruct;
static private mapping destructing = ([]);
varargs void destruct(object ob, int flag) {
if (flag && !member(destructing, ob)) {
if (last_destruct != time())
destructing = allocate_mapping(0,0);
destructing += ([ob]);
ob->destructor();
}
efun::destruct(ob);
}
/*
* The ls() function is no longer needed, as get_dir() can do the same
* work.
*/
void ls(string path) {
int max, i, len, tmp;
status trunc_flag;
mixed *dir;
set_this_object(previous_object());
if (!path)
path = ".";
dir = get_dir (path,3);
#if defined(COMPAT_FLAG) && 0
if (path[0] == '/')
path = extract(path, 1);
if (path != "")
path += "/";
#else
if (path != "/")
path += "/";
#endif
if (!dir) {
write("No such directory.\n");
return;
}
if (sizeof(dir) > 999)
{
dir = dir[0..998];
trunc_flag = 1;
}
for(i = sizeof(dir); i--; ) {
if(dir[i--] == -2)
dir[i]+="/";
len = strlen(dir[i]);
if (len > max)
max = len;
}
++max;
if (max > 79)
max = 79;
for (i=0; i < sizeof(dir); i+=2) {
string name;
name = dir[i];
tmp = strlen(name);
if (len + tmp > 79) {
len = 0;
write("\n");
}
write(name);
if (len + max > 79) {
write("\n");
len = 0;
} else {
write(extract(
" ",
80-max+tmp));
len += max;
}
}
write("\n");
if (trunc_flag) write("***TRUNCATED***\n");
}
#if 0 /* This is probably too costly; just replace this_player(1) with
this_interactive() */
/*
* Not accurate.
* Original behaviour: if arg _supplied_ return current_interactive.
*/
varargs object this_player(int x)
{
return x ? this_interactive() : efun::this_player();
}
#endif

11
mudlib/sys/comm.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef LPC_COMM_H_
#define LPC_COMM_H_
/* Mode values recognized by the efun get_combine_charset()
* and get_connection_charset() */
#define CHARSET_VECTOR 0 /* Return the charset as bitvector array */
#define CHARSET_STRING 1 /* Return the charset as string */
#define CHARSET_QUOTE_IAC 2 /* Return the status of the IAC quoting */
#endif /* LPC_COMM_H_ */

50
mudlib/sys/commands.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef LPC_COMMANDS_H_
#define LPC_COMMANDS_H_
/* Flags accepted by add_action(fun, verb, flag).
* (Below, VERB is what the player enters).
* Negative flag values allow VERB to be just the first -<flag>
* characters of <verb> (abbreviated verb).
*/
#define AA_VERB 0 /* VERB must be <verb> */
#define AA_SHORT 1 /* VERB must start with <verb>,
* args do not include extra characters */
#define AA_NOSPACE 2 /* VERB must start with <verb>,
* args and verb do include extra characters */
#define AA_IMM_ARGS 3 /* VERB must start with <verb>,
* args do include extra characters */
/* Bitflags accepted by query_actions(object ob, int mask)
*/
#define QA_VERB 1
#define QA_TYPE 2
#define QA_SHORT_VERB 4
#define QA_OBJECT 8
#define QA_FUNCTION 16
/* Indices in the arrays returned from command_stack()
*/
#define CMD_VERB 0
#define CMD_TEXT 1
#define CMD_ORIGIN 2
#define CMD_PLAYER 3
#define CMD_FAIL 4
#define CMD_FAILOBJ 5
#define CMD_SIZE 6
/* Indices into the subarrays returned from match_command()
*/
#define CMDM_VERB 0
#define CMDM_ARG 1
#define CMDM_OBJECT 2
#define CMDM_FUN 3
#define CMDM_SIZE 4
#endif /* LPC_COMMANDS_H_ */

240
mudlib/sys/debug_info.h Normal file
View File

@ -0,0 +1,240 @@
#ifndef LPC_DEBUG_INFO_H_
#define LPC_DEBUG_INFO_H_ 1
/* Request values for efun debug_info().
*/
#define DINFO_OBJECT 0 /* Print information about an object */
#define DINFO_MEMORY 1 /* Print memory usage of an object */
#define DINFO_OBJLIST 2 /* Return an object from the global list */
#define DINFO_MALLOC 3 /* Print the information from the 'malloc' cmd */
#define DINFO_STATUS 4 /* Return the 'status' information */
#define DINFO_DUMP 5 /* Dump some special information into files */
#define DINFO_DATA 6 /* Return internal information */
#define DINFO_TRACE 7 /* Return the current call trace */
/* Sub-request values for debug_info(DINFO_DATA) */
#define DID_STATUS 0 /* Return the 'status' and 'status tables' information */
#define DID_SWAP 1 /* Return the 'status swap' information */
#define DID_MEMORY 2 /* Return the 'status malloc' information */
/* Sub-request values for debug_info(DINFO_TRACE) */
#define DIT_CURRENT 0 /* Return the current call chain as an array */
#define DIT_ERROR 1 /* Return the last error call chain as an array */
#define DIT_UNCAUGHT_ERROR 2 /* Return the last uncaught error call chain */
#define DIT_STR_CURRENT 3 /* Return the current call chain as a string */
/* Indices into the array resulting from debug_info(DINFO_DATA, DID_STATUS)
*/
#define DID_ST_ACTIONS 0
#define DID_ST_ACTIONS_SIZE 1
#define DID_ST_SHADOWS 2
#define DID_ST_SHADOWS_SIZE 3
#define DID_ST_OBJECTS 4
#define DID_ST_OBJECTS_SIZE 5
#define DID_ST_OBJECTS_SWAPPED 6
#define DID_ST_OBJECTS_SWAP_SIZE 7
#define DID_ST_OBJECTS_LIST 8
#define DID_ST_OBJECTS_NEWLY_DEST 9
#define DID_ST_OBJECTS_DESTRUCTED 10
#define DID_ST_OBJECTS_PROCESSED 11
#define DID_ST_OBJECTS_AVG_PROC 12
#define DID_ST_OTABLE 13
#define DID_ST_OTABLE_SLOTS 14
#define DID_ST_OTABLE_SIZE 15
#define DID_ST_HBEAT_OBJS 16
#define DID_ST_HBEAT_CALLS 17
#define DID_ST_HBEAT_CALLS_TOTAL 18
#define DID_ST_HBEAT_SLOTS 19
#define DID_ST_HBEAT_SIZE 20
#define DID_ST_HBEAT_PROCESSED 21
#define DID_ST_HBEAT_AVG_PROC 22
#define DID_ST_CALLOUTS 23
#define DID_ST_CALLOUT_SIZE 24
#define DID_ST_ARRAYS 25
#define DID_ST_ARRAYS_SIZE 26
#define DID_ST_MAPPINGS 27
#define DID_ST_MAPPINGS_SIZE 28
#define DID_ST_HYBRID_MAPPINGS 51
#define DID_ST_HASH_MAPPINGS 54
#define DID_ST_STRUCTS 29
#define DID_ST_STRUCTS_SIZE 30
#define DID_ST_STRUCT_TYPES 31
#define DID_ST_STRUCT_TYPES_SIZE 32
#define DID_ST_PROGS 33
#define DID_ST_PROGS_SIZE 34
#define DID_ST_PROGS_SWAPPED 35
#define DID_ST_PROGS_SWAP_SIZE 36
#define DID_ST_USER_RESERVE 37
#define DID_ST_MASTER_RESERVE 38
#define DID_ST_SYSTEM_RESERVE 39
#define DID_ST_ADD_MESSAGE 40
#define DID_ST_PACKETS 41
#define DID_ST_PACKET_SIZE 42
#define DID_ST_PACKETS_IN 43
#define DID_ST_PACKET_SIZE_IN 44
#define DID_ST_APPLY 45
#define DID_ST_APPLY_HITS 46
#define DID_ST_STRINGS 47
#define DID_ST_STRING_SIZE 48
#define DID_ST_STR_TABLE_SIZE 49
#define DID_ST_STR_OVERHEAD 50
#define DID_ST_UNTABLED 52
#define DID_ST_UNTABLED_SIZE 53
#define DID_ST_UNUSED54 54 /* UNUSED */
#define DID_ST_UNUSED55 55 /* UNUSED */
#define DID_ST_TABLED 56
#define DID_ST_TABLED_SIZE 57
#define DID_ST_STR_SEARCHES 58
#define DID_ST_STR_SEARCHLEN 59
#define DID_ST_STR_SEARCHES_BYVALUE 60
#define DID_ST_STR_SEARCHLEN_BYVALUE 61
#define DID_ST_STR_CHAINS 62
#define DID_ST_STR_ADDED 63
#define DID_ST_STR_DELETED 64
#define DID_ST_STR_COLLISIONS 65
#define DID_ST_STR_FOUND 66
#define DID_ST_STR_FOUND_BYVALUE 67
#define DID_ST_RX_CACHED 68
#define DID_ST_RX_TABLE 69
#define DID_ST_RX_TABLE_SIZE 70
#define DID_ST_RX_REQUESTS 71
#define DID_ST_RX_REQ_FOUND 72
#define DID_ST_RX_REQ_COLL 73
#define DID_ST_MB_FILE 74
#define DID_ST_MB_SWAP 75
#define DID_ST_BOOT_TIME 76
#define DID_STATUS_MAX 77 /* Total number of entries */
/* Indices into the array resulting from debug_info(DINFO_DATA, DID_SWAP)
*/
#define DID_SW_PROGS 0
#define DID_SW_PROG_SIZE 1
#define DID_SW_PROG_UNSWAPPED 2
#define DID_SW_PROG_U_SIZE 3
#define DID_SW_VARS 4
#define DID_SW_VAR_SIZE 5
#define DID_SW_FREE 6
#define DID_SW_FREE_SIZE 7
#define DID_SW_FILE_SIZE 8
#define DID_SW_REUSED 9
#define DID_SW_SEARCHES 10
#define DID_SW_SEARCH_LEN 11
#define DID_SW_F_SEARCHES 12
#define DID_SW_F_SEARCH_LEN 13
#define DID_SW_COMPACT 14
#define DID_SW_RECYCLE_FREE 15
#define DID_SWAP_MAX 16
/* Indices into the array resulting from debug_info(DINFO_DATA, DID_MEMORY)
*/
#define DID_MEM_NAME 0
#define DID_MEM_SBRK 1
#define DID_MEM_SBRK_SIZE 2
#define DID_MEM_LARGE 3
#define DID_MEM_LARGE_SIZE 4
#define DID_MEM_MMAP (DID_MEM_LARGE)
#define DID_MEM_MMAP_SIZE (DID_MEM_LARGE_SIZE)
#define DID_MEM_LFREE 5
#define DID_MEM_FREE_CHUNKS (DID_MEM_LFREE)
#define DID_MEM_LFREE_SIZE 6
#define DID_MEM_LWASTED 7
#define DID_MEM_LWASTED_SIZE 8
#define DID_MEM_KEEP_COST (DID_MEM_LWASTED_SIZE)
#define DID_MEM_CHUNK 9
#define DID_MEM_CHUNK_SIZE 10
#define DID_MEM_SLAB (DID_MEM_CHUNK)
#define DID_MEM_SLAB_SIZE (DID_MEM_CHUNK_SIZE)
#define DID_MEM_MAX_ALLOCATED (DID_MEM_CHUNK_SIZE)
#define DID_MEM_SMALL 11
#define DID_MEM_SMALL_SIZE 12
#define DID_MEM_SFREE 13
#define DID_MEM_SFREE_SIZE 14
#define DID_MEM_FFREE (DID_MEM_SFREE)
#define DID_MEM_FFREE_SIZE (DID_MEM_SFREE_SIZE)
#define DID_MEM_SWASTED 15
#define DID_MEM_SWASTED_SIZE 16
#define DID_MEM_SMALL_OVERHEAD_SIZE (DID_MEM_SWASTED_SIZE)
#define DID_MEM_MINC_CALLS 17
#define DID_MEM_MINC_SUCCESS 19
#define DID_MEM_MINC_SIZE 19
#define DID_MEM_PERM 20
#define DID_MEM_PERM_SIZE 21
#define DID_MEM_CLIB 22
#define DID_MEM_CLIB_SIZE 23
#define DID_MEM_OVERHEAD 24
#define DID_MEM_ALLOCATED 25
#define DID_MEM_USED 26
#define DID_MEM_TOTAL_UNUSED 27
#define DID_MEM_DEFRAG_CALLS 28
#define DID_MEM_DEFRAG_CALLS_REQ 29
#define DID_MEM_SLAB_FREE (DID_MEM_DEFRAG_CALLS)
#define DID_MEM_SLAB_FREE_SIZE (DID_MEM_DEFRAG_CALLS_REQ)
#define DID_MEM_DEFRAG_REQ_SUCCESS 30
#define DID_MEM_DEFRAG_BLOCKS_INSPECTED 31
#define DID_MEM_DEFRAG_BLOCKS_MERGED 32
#define DID_MEM_DEFRAG_BLOCKS_RESULT 33
#define DID_MEM_AVL_NODES 34
#define DID_MEM_EXT_STATISTICS 35
#define DID_MEMORY_MAX 36
/* Indices into the subarrays of DID_MEM_EXT_STATISTICS (if given) */
#define DID_MEM_ES_MAX_ALLOC 0
#define DID_MEM_ES_CUR_ALLOC 1
#define DID_MEM_ES_MAX_FREE 2
#define DID_MEM_ES_CUR_FREE 3
#define DID_MEM_ES_AVG_XALLOC 4
#define DID_MEM_ES_AVG_XFREE 5
#define DID_MEM_ES_FULL_SLABS 6
#define DID_MEM_ES_FREE_SLABS 7
#define DID_MEM_ES_TOTAL_SLABS 8
#define DID_MEM_ES_MAX 9
/* Indices into the subarrays resulting from debug_info(DINFO_TRACE, 0)
*/
#define TRACE_TYPE 0
#define TRACE_NAME 1
#define TRACE_PROGRAM 2
#define TRACE_OBJECT 3
#define TRACE_LOC 4
#define TRACE_MAX 5
/* Values for entry TRACE_TYPE */
#define TRACE_TYPE_SYMBOL 0
#define TRACE_TYPE_SEFUN 1
#define TRACE_TYPE_EFUN 2
#define TRACE_TYPE_LAMBDA 3
#define TRACE_TYPE_LFUN 4
#endif /* LPC_DEBUG_INFO_H_ */

View File

@ -0,0 +1,18 @@
#ifndef LPC_DEBUG_MESSAGE_H_
#define LPC_DEBUG_MESSAGE_H_ 1
/* Definitions and macros for the debug_message() */
#define DMSG_DEFAULT 0 /* log to stdout and .debug.log */
#define DMSG_STDOUT (1 << 0) /* log to stdout */
#define DMSG_STDERR (1 << 1) /* log to stderr */
#define DMSG_LOGFILE (1 << 2) /* log to .debug.log */
#define DMSG_STAMP (1 << 3) /* Prepend the timestamp */
/* Derived macros */
#define DMSG_TARGET (DMSG_STDOUT|DMSG_STDERR|DMSG_LOGFILE)
/* Mask for all target bitflags */
#endif /* LPC_DEBUG_MESSAGE_H_ */

35
mudlib/sys/driver_hook.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef LPC_DRIVER_HOOK_H_
#define LPC_DRIVER_HOOK_H_ 1
/* --- Driver Hooks ---
*/
#define H_MOVE_OBJECT0 0
#define H_MOVE_OBJECT1 1
#define H_LOAD_UIDS 2
#define H_CLONE_UIDS 3
#define H_CREATE_SUPER 4
#define H_CREATE_OB 5
#define H_CREATE_CLONE 6
#define H_RESET 7
#define H_CLEAN_UP 8
#define H_MODIFY_COMMAND 9
#define H_NOTIFY_FAIL 10
#define H_NO_IPC_SLOT 11
#define H_INCLUDE_DIRS 12
#define H_TELNET_NEG 13
#define H_NOECHO 14
#define H_ERQ_STOP 15
#define H_MODIFY_COMMAND_FNAME 16
#define H_COMMAND 17
#define H_SEND_NOTIFY_FAIL 18
#define H_AUTO_INCLUDE 19
#define H_DEFAULT_METHOD 20
#define H_DEFAULT_PROMPT 21
#define H_PRINT_PROMPT 22
#define H_REGEXP_PACKAGE 23
#define NUM_DRIVER_HOOKS 24 /* Number of hooks */
#endif /* LPC_DRIVER_HOOK_ */

59
mudlib/sys/erq.h Normal file
View File

@ -0,0 +1,59 @@
/* external request demon interface definitions */
#ifndef LPC__ERQ_H__
#define LPC__ERQ_H__ 1
/* servive request types */
#define ERQ_RLOOKUP 0 /* Lookup ip -> name */
#define ERQ_EXECUTE 1 /* Execute a program */
#define ERQ_FORK 2 /* Fork a program */
#define ERQ_AUTH 3 /* Connect to a remote authd */
#define ERQ_SPAWN 4 /* Spawn a program */
#define ERQ_SEND 5 /* Send data to a program or connection */
#define ERQ_KILL 6 /* Kill a program or connection */
#define ERQ_OPEN_UDP 7 /* Open a UDP socket */
#define ERQ_OPEN_TCP 8 /* Open a TCP connection */
#define ERQ_LISTEN 9 /* Open a TCP accept-socket */
#define ERQ_ACCEPT 10 /* Accept a connection from a accept-socket */
#define ERQ_LOOKUP 11 /* Lookup name -> ip */
#ifdef __IPV6__
#define ERQ_RLOOKUPV6 12 /* Lookup name/ip6 */
#endif
/* Additional service request type flags evaluated by efun send_erq().
* The ERQ itself won't get to see it.
*/
#define ERQ_CB_STRING (1 << 31) /* Callback closure takes a string arg */
/* answers from ERQ_EXECUTE / ERQ_FORK */
#define ERQ_OK 0
#define ERQ_SIGNALED 1
#define ERQ_E_NOTFOUND 2 /* process not found by wait */
#define ERQ_E_UNKNOWN 3 /* unknown exit condition from wait() */
#define ERQ_E_ARGLENGTH 4
#define ERQ_E_ARGFORMAT 5
#define ERQ_E_ARGNUMBER 6
#define ERQ_E_ILLEGAL 7
#define ERQ_E_PATHLEN 8
#define ERQ_E_FORKFAIL 9
#define ERQ_E_TICKET 11
#define ERQ_E_INCOMPLETE 12
#define ERQ_E_WOULDBLOCK 13
#define ERQ_E_PIPE 14
#define ERQ_STDOUT 15 /* Normal data received */
#define ERQ_STDERR 16
#define ERQ_EXITED 17 /* Connection closed on EOF */
#define ERQ_E_NSLOTS 18
/* reserved handles */
#define ERQ_HANDLE_RLOOKUP (-1)
#define ERQ_HANDLE_KEEP_HANDLE (-2)
#define ERQ_HANDLE_RLOOKUPV6 (-3)
#endif /* LPC__ERQ_H__ */

29
mudlib/sys/files.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef LPC_FILES_H_
#define LPC_FILES_H_ 1
/* Definitions and macros for the various file efuns */
/* Special return values of file_size() and the size part of get_dir().
*/
#define FSIZE_NOFILE -1 /* File doesn't exist or is not readable */
#define FSIZE_DIR -2 /* The file is actually a directory */
/* Flag values for get_dir().
*/
#define GETDIR_EMPTY (0) /* return an empty array (not very useful) */
#define GETDIR_NAMES (0x01) /* return the filenames */
#define GETDIR_SIZES (0x02) /* return the file sizes */
#define GETDIR_DATES (0x04) /* return the dates of last modification */
/* (0x08) unused */
#define GETDIR_ACCESS (0x40) /* return the dates of last access */
#define GETDIR_MODES (0x80) /* return the file mode */
#define GETDIR_PATH (0x10) /* with _NAMES: add the path to the filenames */
#define GETDIR_UNSORTED (0x20) /* return the results unsorted */
#define GETDIR_ALL (0xDF) /* return all */
#endif /* LPC_FILES_H_ */

69
mudlib/sys/functionlist.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef LPC_FUNCTIONLIST_H
#define LPC_FUNCTIONLIST_H
#ifndef __DRIVER_SOURCE__
#include "lpctypes.h"
#define NAME_INHERITED 0x80000000 /* Defined by inheritance */
#define TYPE_MOD_STATIC 0x40000000 /* Static function or variable */
#define TYPE_MOD_NO_MASK 0x20000000 /* The nomask => not redefineable */
#define TYPE_MOD_PRIVATE 0x10000000 /* Can't be inherited */
#define TYPE_MOD_PUBLIC 0x08000000 /* Force inherit through private */
#define TYPE_MOD_VARARGS 0x04000000 /* Used for type checking */
#define TYPE_MOD_VIRTUAL 0x02000000 /* can be re- and cross- defined */
#define TYPE_MOD_PROTECTED 0x01000000 /* cannot be called externally */
#define TYPE_MOD_XVARARGS 0x00800000 /* accepts optional arguments */
#define TYPE_MOD_NOSAVE TYPE_MOD_STATIC /* vars: can't be saved */
/* Internally TYPE_MOD_NOSAVE is 0x00400000, but that never leaves
* the compiler.
*/
#define NAME_CROSS_DEFINED 0x00080000 /* function defined from other program */
#if defined(__LPC_STRUCTS__) || defined(USE_STRUCTS)
#define NAME_HIDDEN 0x00020000 /* Not visible for inheritance */
#define NAME_PROTOTYPE 0x00010000 /* Defined by a prototype only */
#define NAME_UNDEFINED 0x00008000 /* Not defined yet */
#define NAME_TYPES_LOST 0x00004000 /* inherited, no save_types */
#else /* !USE_STRUCTS */
#define NAME_HIDDEN 0x00000800 /* Not visible for inheritance */
#define NAME_PROTOTYPE 0x00000400 /* Defined by a prototype only */
#define NAME_UNDEFINED 0x00000200 /* Not defined yet */
#define NAME_TYPES_LOST 0x00000100 /* inherited, no save_types */
#endif /* USE_STRUCTS */
#endif /* !__DRIVER_SOURCE__ */
/* Return value flag types for functionlist() and variable_list() */
#define RETURN_FUNCTION_NAME 0x01
#define RETURN_FUNCTION_FLAGS 0x02
#define RETURN_FUNCTION_TYPE 0x04
/* Additional return value flag types for functionlist() */
#define RETURN_FUNCTION_NUMARG 0x08
#define RETURN_FUNCTION_ARGTYPE 0x10 /* not implemented */
/* Additional return value flag types for variable_list() */
#define RETURN_VARIABLE_VALUE 0x08
/* Masks of the flag unions allowed for various efuns: */
#define RETURN_FUNCTION_MASK 0x0f /* functionlist() */
#define RETURN_VARIABLE_MASK 0x0f /* variable_list() */
/* Return value flag types for function_exists() */
#define FEXISTS_PROGNAME (0)
#define FEXISTS_FILENAME (1)
#define FEXISTS_LINENO (2)
#define FEXISTS_NUMARG (3)
#define FEXISTS_TYPE (4)
#define FEXISTS_FLAGS (5)
#define FEXISTS_ALL (3)
#endif /* LPC_FUNCTIONLIST_H */

26
mudlib/sys/idn.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef LPC_IDN_H_
#define LPC_IDN_H_ 1
/* --- IDNA Constants ---
*/
/* idna_stringprep() profiles. */
#define STRINGPREP_NAMEPREP 1
#define STRINGPREP_SASLPREP 2
#define STRINGPREP_PLAIN 3
#define STRINGPREP_TRACE 4
#define STRINGPREP_KERBEROS5 5
#define STRINGPREP_XMPP_NODEPREP 6
#define STRINGPREP_XMPP_RESOURCEPREP 7
#define STRINGPREP_ISCSI 8
/* idna_stringprep() flags */
#define STRINGPREP_NO_NFKC_FLAG (1<<0)
#define STRINGPREP_NO_BIDI_FLAG (1<<1)
#define STRINGPREP_NO_UNASSIGNED_FLAG (1<<2)
#define STRINGPREP_FLAG_MAX (1<<2)
#endif

View File

@ -0,0 +1,9 @@
#ifndef LPC_INCLUDE_LIST_H
#define LPC_INCLUDE_LIST_H
/* Return value flag types for include_list() */
#define INCLIST_FLAT 0x00
#define INCLIST_TREE 0x01
#endif /* LPC_INCLUDE_LIST_H */

10
mudlib/sys/inherit_list.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef LPC_INHERIT_LIST_H
#define LPC_INHERIT_LIST_H
/* Return value flag types for inherit_list() */
#define INHLIST_FLAT 0x00
#define INHLIST_TREE 0x01
#define INHLIST_TAG_VIRTUAL 0x02
#endif /* LPC_INHERIT_LIST_H */

18
mudlib/sys/input_to.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef LPC_INPUT_TO_H_
#define LPC_INPUT_TO_H_
/* Mode values recognized by the efun input_to() */
#define INPUT_NOECHO 1 /* Don't echo the next line typed */
#define INPUT_CHARMODE 2 /* Switch into/out of charmode */
#define INPUT_PROMPT 4 /* Use a custom prompt */
#define INPUT_NO_TELNET 8 /* Switch into/out of charmode on the driver
* side only.
*/
#define INPUT_APPEND 16 /* Append the input_to to the list of already
* pending input_to's.
*/
/* #define INPUT_BINARY 32 -- nice, but noone has coded it */
#define INPUT_IGNORE_BANG 128 /* Disallow the '!' escape */
#endif /* LPC_INPUT_TO_H_ */

68
mudlib/sys/lpctypes.h Normal file
View File

@ -0,0 +1,68 @@
#ifndef LPC_LPCTYPES_H
#define LPC_LPCTYPES_H
/* compile time types, from functionlist() */
#define TYPE_UNKNOWN 0 /* This type must be casted */
#define TYPE_NUMBER 1
#define TYPE_STRING 2
#define TYPE_VOID 3
#define TYPE_OBJECT 4
#define TYPE_MAPPING 5
#define TYPE_FLOAT 6
#define TYPE_ANY 7 /* Will match any type */
#define TYPE_CLOSURE 8
#define TYPE_SYMBOL 9
#define TYPE_QUOTED_ARRAY 10
#if defined(USE_STRUCTS) || defined(__LPC_STRUCTS__)
#define TYPE_STRUCT 11
#endif
#define TYPE_MOD_POINTER 0x0040 /* Pointer to a basic type */
/* runtime types, from typeof() */
#define T_INVALID 0x0
#define T_LVALUE 0x1
#define T_NUMBER 0x2
#define T_STRING 0x3
#define T_POINTER 0x4
#define T_OBJECT 0x5
#define T_MAPPING 0x6
#define T_FLOAT 0x7
#define T_CLOSURE 0x8
#define T_SYMBOL 0x9
#define T_QUOTED_ARRAY 0xa
#if defined(USE_STRUCTS) || defined(__LPC_STRUCTS__)
#define T_STRUCT 0xb
#endif
/* Closure types, stored as secondary type info */
#ifndef __DRIVER_SOURCE__
#define CLOSURE_LFUN 0 /* lfun in an object */
/* Code 1: currently unused, used to be CLOSURE_ALIEN_LFUN */
#define CLOSURE_IDENTIFIER 2 /* variable in this object */
#define CLOSURE_PRELIMINARY 3
/* Efun closure used in a static initialization */
#define CLOSURE_BOUND_LAMBDA 4 /* Bound unbound-lambda closure */
#define CLOSURE_LAMBDA 5 /* normal lambda closure */
#define CLOSURE_UNBOUND_LAMBDA 6 /* unbound lambda closure. */
#define CLOSURE_OPERATOR (0xe800)
#define CLOSURE_EFUN (0xf000)
#define CLOSURE_SIMUL_EFUN (0xf800)
#define CLOSURE_IS_LFUN(x) (((x)&~1) == 0)
#define CLOSURE_IS_IDENTIFIER(x) ((x) == CLOSURE_IDENTIFIER)
#define CLOSURE_IS_BOUND_LAMBDA(x) ((x) == CLOSURE_BOUND_LAMBDA)
#define CLOSURE_IS_LAMBDA(x) ((x) == CLOSURE_LAMBDA)
#define CLOSURE_IS_UNBOUND_LAMBDA(x) ((x) == CLOSURE_UNBOUND_LAMBDA)
#define CLOSURE_IS_SIMUL_EFUN(x) (((x) & 0xf800) == CLOSURE_SIMUL_EFUN)
#define CLOSURE_IS_EFUN(x) (((x) & 0xf800) == CLOSURE_EFUN)
#define CLOSURE_IS_OPERATOR(x) (((x) & 0xf800) == CLOSURE_OPERATOR)
#endif /* __DRIVER_SOURCE__ */
#endif /* LPC_LPCTYPES_H */

83
mudlib/sys/objectinfo.h Normal file
View File

@ -0,0 +1,83 @@
#ifndef LPC_OBJECTINFO_H_
#define LPC_OBJECTINFO_H_
/* Definition of argument values for object_info() and
* of the indices in the corresponding result arrays.
*/
/* Possible types of information requested from object_info()
*/
#define OINFO_BASIC 0
#define OINFO_POSITION 1
#define OINFO_MEMORY 2
/* Indices in the array resulting from OINFO_BASIC
*/
#define OIB_HEART_BEAT 0
#define OIB_IS_WIZARD 1
#define OIB_ENABLE_COMMANDS 2
#define OIB_CLONE 3
#define OIB_DESTRUCTED 4
#define OIB_SWAPPED 5
#define OIB_ONCE_INTERACTIVE 6
#define OIB_RESET_STATE 7
#define OIB_WILL_CLEAN_UP 8
#define OIB_LAMBDA_REFERENCED 9
#define OIB_SHADOW 10
#define OIB_REPLACED 11
#define OIB_TOTAL_LIGHT 12
#define OIB_NEXT_RESET 13
#define OIB_TIME_OF_REF 14
#define OIB_REF 15
#define OIB_GIGATICKS 16
#define OIB_TICKS 17
#define OIB_SWAP_NUM 18
#define OIB_PROG_SWAPPED 19
#define OIB_VAR_SWAPPED 20
#define OIB_NAME 21
#define OIB_LOAD_NAME 22
#define OIB_NEXT_ALL 23
#define OIB_PREV_ALL 24
#define OIB_NEXT_CLEANUP 25
#define OIB_MAX 26 /* Number of OIB_ result elements */
/* Indices in the array resulting from OINFO_POSITION
*/
#define OIP_NEXT 0
#define OIP_PREV 1
#define OIP_POS 2
#define OIP_MAX 3 /* Number of OIP_ result elements */
/* Indices in the array resulting from OINFO_MEMORY
*/
#define OIM_REF 0
#define OIM_NAME 1
#define OIM_PROG_SIZE 2
#define OIM_NUM_FUNCTIONS 3
#define OIM_SIZE_FUNCTIONS 4
#define OIM_NUM_VARIABLES 5
#define OIM_SIZE_VARIABLES 6
#define OIM_NUM_STRINGS 7
#define OIM_SIZE_STRINGS 8
#define OIM_SIZE_STRINGS_DATA 9
#define OIM_SIZE_STRINGS_TOTAL 10
#define OIM_NUM_INHERITED 11
#define OIM_SIZE_INHERITED 12
#define OIM_TOTAL_SIZE 13
#define OIM_DATA_SIZE 14
#define OIM_TOTAL_DATA_SIZE 15
#define OIM_NO_INHERIT 16
#define OIM_NO_CLONE 17
#define OIM_NO_SHADOW 18
#define OIM_NUM_INCLUDES 19
#define OIM_SHARE_VARIABLES 20
#define OIM_MAX 21 /* Number of OIM_ result elements */
#endif /* LPC_OBJECTINFO_H_ */

23
mudlib/sys/pgsql.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _PGSQL_H
#define _PGSQL_H
/* Definitions for the PostgreSQL efuns */
#define PGRES_EMPTY_QUERY 0 /* Unimplemented */
#define PGRES_COMMAND_OK 1
#define PGRES_TUPLES_OK 2
#define PGRES_COPY_OUT 3 /* Unimplemented */
#define PGRES_COPY_IN 4 /* Unimplemented */
#define PGRES_BAD_RESPONSE 5
#define PGRES_NONFATAL_ERROR 6
#define PGRES_FATAL_ERROR 7
#define PGRES_NOTICE 99
#define PGCONN_SUCCESS 100
#define PGCONN_FAILED 101
#define PGCONN_ABORTED 102
#define PG_RESULT_ARRAY 0
#define PG_RESULT_MAP 1
#endif

43
mudlib/sys/regexp.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef LPC_REGEXP_H_
#define LPC_REGEXP_H_ 1
/* Definitions of regexp option values */
/* Not really an RE option, but used in conjunction with some RE functions: */
#define RE_GLOBAL 0x0001 /* Apply RE globally (if possible) */
/* Options supported by the old regexp package: */
#define RE_EXCOMPATIBLE 0x0002 /* RE is compatible with ex */
/* Options supported by the PCRE regexp package: */
#define RE_CASELESS 0x0004
#define RE_MULTILINE 0x0008
#define RE_DOTALL 0x0010
#define RE_EXTENDED 0x0020
#define RE_ANCHORED 0x0040
#define RE_DOLLAR_ENDONLY 0x0080
#define RE_NOTBOL 0x0100
#define RE_NOTEOL 0x0200
#define RE_UNGREEDY 0x0400
#define RE_NOTEMPTY 0x0800
#define RE_UTF8 0x1000
/* Options specific for regmatch(): */
#define RE_MATCH_SUBS 0x00100000 /* Return matched subexpressions */
/* Options specific for regexplode(): */
#define RE_OMIT_DELIM 0x00100000 /* Omit the delimiters */
/* Regexp package selection options: */
#define RE_TRADITIONAL 0x04000000
#define RE_PCRE 0x02000000
#define RE_PACKAGE_MASK (RE_TRADITIONAL | RE_PCRE)
#endif /* LPC_REGEXP_H_ */

24
mudlib/sys/rtlimits.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef LPC_RTLIMITS_H_
#define LPC_RTLIMITS_H_
/* Runtime limit index/tag values */
#define LIMIT_EVAL (0)
#define LIMIT_ARRAY (1)
#define LIMIT_MAPPING (2)
#define LIMIT_MAPPING_KEYS LIMIT_MAPPING
#define LIMIT_MAPPING_SIZE (3)
#define LIMIT_BYTE (4)
#define LIMIT_FILE (5)
#define LIMIT_CALLOUTS (6)
#define LIMIT_COST (7)
#define LIMIT_MAX (8) /* Number of recognized limits */
/* Special limit values */
#define LIMIT_UNLIMITED 0 /* No limit */
#define LIMIT_KEEP (-1) /* Keep the old limit setting */
#define LIMIT_DEFAULT (-2) /* Use the default setting */
#endif /* LPC_RTLIMITS_H_ */

10
mudlib/sys/sent.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef LPC_SENT_H_
#define LPC_SENT_H_
#define SENT_PLAIN 0
#define SENT_SHORT_VERB 1
#define SENT_NO_SPACE 2
#define SENT_NO_VERB 3
#define SENT_MARKER 4
#endif

10
mudlib/sys/strings.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef LPC_STRINGS_H_
#define LPC_STRINGS_H_ 1
/* 'where' argument values for trim() */
#define TRIM_LEFT 0x01
#define TRIM_RIGHT 0x02
#define TRIM_BOTH (TRIM_LEFT|TRIM_RIGHT)
#endif /* LPC_STRINGS_H_ */

38
mudlib/sys/struct_info.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef LPC_STRUCTINFO_H_
#define LPC_STRUCTINFO_H_
#ifndef __DRIVER_SOURCE__
#include "lpctypes.h"
#endif
/* Definition of argument values for struct_info() and
* of the indices in the corresponding result arrays.
*/
/* Possible types of information requested from struct_info()
*/
#define SINFO_FLAT 0
#define SINFO_NESTED 1
/* Indices in the result array
*/
#define SI_NAME 0
#define SI_PROG_NAME 1
#define SI_PROG_ID 2
#define SI_BASE 3
#define SI_MEMBER 4
#define SI_MAX 5 /* Min Number of SI_ result elements */
/* Indices in the SI_MEMBER arrays
*/
#define SIM_NAME 0
#define SIM_TYPE 1
#define SIM_EXTRA 2
#define SIM_MAX 3 /* Number of SIM_ elements */
#endif /* LPC_STRUCTINFO_H_ */

217
mudlib/sys/telnet.h Normal file
View File

@ -0,0 +1,217 @@
#ifndef TELNET_H__
#define TELNET_H__ 1
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* @(#)telnet.h 5.7 (Berkeley) 11/14/89
*/
/*
* Definitions for the TELNET protocol.
*/
#define IAC 255 /* interpret as command: */
#define DONT 254 /* you are not to use option */
#define DO 253 /* please, you use option */
#define WONT 252 /* I won't use option */
#define WILL 251 /* I will use option */
#define SB 250 /* interpret as subnegotiation */
#define GA 249 /* you may reverse the line */
#define EL 248 /* erase the current line */
#define EC 247 /* erase the current character */
#define AYT 246 /* are you there */
#define AO 245 /* abort output--but let prog finish */
#define IP 244 /* interrupt process--permanently */
#define BREAK 243 /* break */
#define DM 242 /* data mark--for connect. cleaning */
#define NOP 241 /* nop */
#define SE 240 /* end sub negotiation */
#define EOR 239 /* end of record (transparent mode) */
#define ABORT 238 /* Abort process */
#define SUSP 237 /* Suspend process */
#define xEOF 236 /* End of file: EOF is already used... */
#define SYNCH 242 /* for telfunc calls */
#ifdef __DRIVER_SOURCE__
#ifdef TELCMDS
char *telcmds[] = {
"EOF", "SUSP", "ABORT", "EOR",
"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC",
};
#define TELCMD_FIRST xEOF
#define TELCMD_LAST IAC
#define TELCMD_OK(x) ((x) <= TELCMD_LAST && (x) >= TELCMD_FIRST)
#define TELCMD(x) telcmds[(x)-TELCMD_FIRST]
#endif
#endif /* __DRIVER_SOURCE__ */
/* telnet options */
#define TELOPT_BINARY 0 /* 8-bit data path */
#define TELOPT_ECHO 1 /* echo */
#define TELOPT_RCP 2 /* prepare to reconnect */
#define TELOPT_SGA 3 /* suppress go ahead */
#define TELOPT_NAMS 4 /* approximate message size */
#define TELOPT_STATUS 5 /* give status */
#define TELOPT_TM 6 /* timing mark */
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
#define TELOPT_NAOL 8 /* negotiate about output line width */
#define TELOPT_NAOP 9 /* negotiate about output page size */
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
#define TELOPT_XASCII 17 /* extended ascic character set */
#define TELOPT_LOGOUT 18 /* force logout */
#define TELOPT_BM 19 /* byte macro */
#define TELOPT_DET 20 /* data entry terminal */
#define TELOPT_SUPDUP 21 /* supdup protocol */
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
#define TELOPT_SNDLOC 23 /* send location */
#define TELOPT_TTYPE 24 /* terminal type */
#define TELOPT_EOR 25 /* end or record */
#define TELOPT_TUID 26 /* TACACS user identification */
#define TELOPT_OUTMRK 27 /* output marking */
#define TELOPT_TTYLOC 28 /* terminal location number */
#define TELOPT_3270REGIME 29 /* 3270 regime */
#define TELOPT_X3PAD 30 /* X.3 PAD */
#define TELOPT_NAWS 31 /* window size */
#define TELOPT_TSPEED 32 /* terminal speed */
#define TELOPT_LFLOW 33 /* remote flow control */
#define TELOPT_LINEMODE 34 /* Linemode option */
#define TELOPT_XDISPLOC 35 /* X Display Location */
#define TELOPT_ENVIRON 36 /* Environment opt for Port ID */
#define TELOPT_AUTHENTICATION 37 /* authentication */
#define TELOPT_ENCRYPT 38 /* authentication */
#define TELOPT_NEWENV 39 /* Environment opt for Port ID */
#define TELOPT_STARTTLS 46 /* Transport Layer Security */
/* Inofficial, mud specific telnet options */
#define TELOPT_COMPRESS 85 /* Mud Compression Protocol, v.1 */
#define TELOPT_COMPRESS2 86 /* Mud Compression Protocol, v.2 */
#define TELOPT_MSP 90 /* Mud Sound Protocol */
#define TELOPT_MXP 91 /* Mud Extension Protocol */
#define TELOPT_EXOPL 255 /* extended-options-list */
#define NTELOPTS 256 /* was: (1+TELOPT_NEWENV) */
#ifdef __DRIVER_SOURCE__
#ifdef TELOPTS
char *telopts[NTELOPTS]
= { "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD"
, "NAME", "STATUS", "TIMING MARK", "RCTE"
, "NAOL", "NAOP", "NAOCRD", "NAOHTS"
, "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD"
, "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO"
, "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION"
, "TERMINAL TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING"
, "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS"
, "TSPEED", "LFLOW", "LINEMODE", "XDISPLOC"
, "ENVIRON", "AUTH", "ENCRYPT", "NEWENV"
, "TELOPT 40", "TELOPT 41", "TELOPT 42", "TELOPT 43"
, "TELOPT 44", "TELOPT 45", "STARTTLS", "TELOPT 47"
, "TELOPT 48", "TELOPT 49", "TELOPT 50", "TELOPT 51"
, "TELOPT 52", "TELOPT 53", "TELOPT 54", "TELOPT 55"
, "TELOPT 56", "TELOPT 57", "TELOPT 58", "TELOPT 59"
, "TELOPT 60", "TELOPT 61", "TELOPT 62", "TELOPT 63"
, "TELOPT 64", "TELOPT 65", "TELOPT 66", "TELOPT 67"
, "TELOPT 68", "TELOPT 69", "TELOPT 70", "TELOPT 71"
, "TELOPT 72", "TELOPT 73", "TELOPT 74", "TELOPT 75"
, "TELOPT 76", "TELOPT 77", "TELOPT 78", "TELOPT 79"
, "TELOPT 80", "TELOPT 81", "TELOPT 82", "TELOPT 83"
, "TELOPT 84", "MUD COMPRESS", "MUD COMPRESS2", "TELOPT 87"
, "TELOPT 88", "TELOPT 89", "MUD SOUND", "MUD EXTENSION"
};
#define TELOPT_FIRST TELOPT_BINARY
#define TELOPT_LAST TELOPT_MXP
#define TELOPT_OK(x) ((x) <= TELOPT_LAST && (x) >= TELOPT_FIRST)
#define TELOPT(x) telopts[(x)-TELOPT_FIRST]
#endif
#endif /* __DRIVER_SOURCE__ */
/* sub-option qualifiers */
#define TELQUAL_IS 0 /* option is... */
#define TELQUAL_SEND 1 /* send option */
/*
* LINEMODE suboptions
*/
#define LM_MODE 1
#define LM_FORWARDMASK 2
#define LM_SLC 3
#define MODE_EDIT 0x01
#define MODE_TRAPSIG 0x02
#define MODE_ACK 0x04
#define MODE_MASK (MODE_EDIT|MODE_TRAPSIG|MODE_ACK)
/* Not part of protocol, but needed to simplify things... */
#define MODE_FLOW 0x0100
#define MODE_ECHO 0x0200
#define MODE_INBIN 0x0400
#define MODE_OUTBIN 0x0800
#define MODE_FORCE 0x1000
#define SLC_SYNCH 1
#define SLC_BRK 2
#define SLC_IP 3
#define SLC_AO 4
#define SLC_AYT 5
#define SLC_EOR 6
#define SLC_ABORT 7
#define SLC_EOF 8
#define SLC_SUSP 9
#define SLC_EC 10
#define SLC_EL 11
#define SLC_EW 12
#define SLC_RP 13
#define SLC_LNEXT 14
#define SLC_XON 15
#define SLC_XOFF 16
#define SLC_FORW1 17
#define SLC_FORW2 18
#define NSLC 18
#define SLC_NAMES "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
"LNEXT", "XON", "XOFF", "FORW1", "FORW2"
#define SLC_NOSUPPORT 0
#define SLC_CANTCHANGE 1
#define SLC_VARIABLE 2
#define SLC_DEFAULT 3
#define SLC_LEVELBITS 0x03
#define SLC_FUNC 0
#define SLC_FLAGS 1
#define SLC_VALUE 2
#define SLC_ACK 0x80
#define SLC_FLUSHIN 0x40
#define SLC_FLUSHOUT 0x20
#endif /* TELNET_H__ */

18
mudlib/sys/time.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef LPC_TIME_H_
#define LPC_TIME_H_ 1
/* Indices into the array returned from gmtime() and localtime(). */
#define TM_SEC 0 /* Seconds (0..59) */
#define TM_MIN 1 /* Minutes (0..59) */
#define TM_HOUR 2 /* Hours (0..23) */
#define TM_MDAY 3 /* Day of the month (1..31) */
#define TM_MON 4 /* Month of the year (0..11) */
#define TM_YEAR 5 /* Year (e.g. 2001) */
#define TM_WDAY 6 /* Day of the week (Sunday = 0) */
#define TM_YDAY 7 /* Day of the year (0..365) */
#define TM_ISDST 8 /* TRUE: Daylight saving time */
#define TM_MAX 9 /* Number of entries in the array */
#endif /* LPC_TIME_H_ */

87
mudlib/sys/tls.h Normal file
View File

@ -0,0 +1,87 @@
#ifndef LPC_TLS_H
#define LPC_TLS_H
/* Field indices for the result of tls_query_connection_info() */
#define TLS_CIPHER 0
#define TLS_COMP 1
#define TLS_KX 2
#define TLS_MAC 3
#define TLS_PROT 4
#define TLS_SESSION 5
#define TLS_INFO_MAX 6 /* Total number of result fields */
/* Interpretation of the cipher information */
#define TLS_CIPHER_TABLE ({ \
"TLS_CIPHER_NONE", \
"TLS_CIPHER_NULL", \
"TLS_CIPHER_ARCFOUR_128", \
"TLS_CIPHER_3DES_CBC", \
"TLS_CIPHER_RIJNDAEL_128_CBC", \
"TLS_CIPHER_RIJNDAEL_256_CBC", \
"TLS_CIPHER_ARCFOUR_40" \
})
#define TLS_CIPHER_NAME(x) TLS_CIPHER_TABLE[(x)]
/* Interpretation of the key-exchange information */
#define TLS_KX_TABLE ({ \
"TLS_KX_NONE", \
"TLS_KX_RSA", \
"TLS_KX_DHE_DSS", \
"TLS_KX_DHE_RSA", \
"TLS_KX_ANON_DH", \
"TLS_KX_SRP", \
"TLS_KX_RSA_EXPORT", \
"TLS_KX_SRP_RSA", \
"TLS_KX_SRP_DSS" \
})
#define TLS_KX_NAME(x) TLS_KX_TABLE[(x)]
/* Interpretation of the MAC information */
#define TLS_MAC_TABLE ({ \
"TLS_MAC_NONE", \
"TLS_MAC_NULL", \
"TLS_MAC_MD5", \
"TLS_MAC_SHA" \
})
#define TLS_MAC_NAME(x) TLS_MAC_TABLE[(x)]
/* Interpretation of the compression information */
#define TLS_COMP_TABLE ({ \
"TLS_COMP_NONE", \
"TLS_COMP_NULL", \
"TLS_COMP_ZLIB", \
"TLS_COMP_LZO" \
})
#define TLS_COMP_NAME(x) TLS_COMP_TABLE[(x)]
/* Interpretation of the protocol information */
#define TLS_PROT_TABLE ({ \
"TLS_PROT_NONE", \
"TLS_PROT_SSL3", \
"TLS_PROT_TLS1" \
})
#define TLS_PROT_NAME(x) TLS_PROT_TABLE[(x)]
/* Recognized hash() algorithms (not all may be supported at runtime) */
#define TLS_HASH_SHA1 (1)
#define TLS_HASH_SHA224 (2)
#define TLS_HASH_SHA256 (3)
#define TLS_HASH_SHA384 (4)
#define TLS_HASH_SHA512 (5)
#define TLS_HASH_MD5 (6)
#define TLS_HASH_RIPEMD160 (7)
#endif /* LPC_TLS_H */

18
mudlib/sys/trace.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef LPC_TRACE_H_
#define LPC_TRACE_H_
/* Argument values for the trace() efun.
*/
#define TRACE_NOTHING 0 /* Stop tracing */
#define TRACE_CALL 1 /* Trace all lfun calls */
#define TRACE_CALL_OTHER 2 /* Trace inter-object calls */
#define TRACE_RETURN 4 /* Trace function returns */
#define TRACE_ARGS 8 /* Print function arguments and results */
#define TRACE_EXEC 16 /* Trace all executed instructions */
#define TRACE_HEART_BEAT 32 /* Trace heartbeat code */
#define TRACE_APPLY 64 /* Trace (internal) applies */
#define TRACE_OBJNAME 128 /* Print the object names */
#endif /* LPC_TRACE_H_ */

22
mudlib/sys/wizlist.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef LPC_WIZLIST_H_
#define LPC_WIZLIST_H_ 1
/* Indices returned by wizlist_info()
*/
#define WL_NAME 0 /* Wizard name */
#define WL_COMMANDS 1 /* Number of commands executed */
#define WL_COST 2 /* Weighted evalcost spent on this wizard */
#define WL_GIGACOST 3 /* Weighted giga-evalcost spent on this wizard */
#define WL_TOTAL_COST 4 /* Total evalcost spent on this wizard */
#define WL_TOTAL_GIGACOST 5 /* Total giga-evalcost spent on this wizard */
#define WL_HEART_BEATS 6 /* Heartbeats spent on this wizard */
#define WL_CALL_OUT 7 /* unimplemented */
#define WL_ARRAY_TOTAL 8 /* Arrays accounted for */
#define WL_MAPPING_TOTAL 9 /* Mappings accounted for */
#define WL_STRUCT_TOTAL 10 /* Struct elements accounted for */
#define WL_EXTRA 11 /* Extra Wizinfo, if set */
#define WL_SIZE 12 /* Number of entries */
#endif /* LPC_WIZLIST_H_ */

1247
mudlib/telnetneg.c Normal file

File diff suppressed because it is too large Load Diff

277
mudlib/telnetneg.h Normal file
View File

@ -0,0 +1,277 @@
//
// Wunderland Mudlib
//
// telnet.h -- Standard telnet definitions
//
// $Log: telnetneg.h,v $
// Revision 1.1.1.1 2006/07/10 02:42:09 lynx
// ldmud 3.3.714
//
// Revision 1.10 2002/12/02 17:31:56 Fiona
// sb_ttype und sb_xdisp
//
#ifndef __TELNET_H__
#define __TELNET_H__
// ******************** Telnet State Machine ********************
// Each option could be in one of the following four states. There
// is also a one element queue for each option. Mind that each option
// could have different states for the lokal and the remote system.
// Six bits of TS_STATE are used.
#define NO 0x00 // option is deactivated
#define YES 0x01 // option is activated
#define WANT_NO 0x02 // option is activated, negotiating to switch off
#define WANT_YES 0x03 // option is deactivated, negotiating to switch on
#define Q_EMPTY 0x00 // no entry in queue
#define Q_OPPOSITE 0x04 // request to toggle state in queue
#define REJECTED 0x08 // option denied, don't retry
// State and queue on the remote side (DO + DONT) (bits 0-3)
#define Q_REMOTE(x) ((x) & 0x03)
#define S_REMOTE(x, y) (((x) & ~0x03) | (y))
#define Q_REMOTEQ(x) ((x) & 0x04)
#define S_REMOTEQ(x, y) (((x) & ~0x04) | (y))
#define Q_REMOTER(x) ((x) & 0x08)
#define S_REMOTER(x, y) (((x) & ~0x08) | (y))
// State and queue on this side (WILL + WONT) (bits 4-7)
#define Q_LOCAL(x) (((x) & 0x30) >> 4)
#define S_LOCAL(x,y) (((x) & ~0x30) | ((y) << 4))
#define Q_LOCALQ(x) (((x) & 0x40) >> 4)
#define S_LOCALQ(x, y) (((x) & ~0x40) | ((y) << 4))
#define Q_LOCALR(x) (((x) & 0x80) >> 4)
#define S_LOCALR(x, y) (((x) & ~0x80) | ((y) << 4))
// Access to mapping ts
#define TS_STATE 0 // option state (yes, no, want yes, want no, Q)
#define TS_SB 1 // sb infos (option specific)
#define TS_R_AGREE 2 // preference or decision callback (remote state)
#define TS_L_AGREE 3 // preference or decision callback (local state)
#define TS_CB 4 // option state change callback (yes, no)
#define TS_SBCB 5 // option sb callback
#define TS_SIZE 6
// To have everything in one place we have one special key in ts
#define TS_EXTRA -1 // key
#define TSE_STATE 0 // input_to's INPUT_NOECHO and/or INPUT_CHARMODE
#define TSE_TELNETNEG 1 // client answered a negotiation
#define TSE_LOG 2 // negotiation log
// Bits used for the charmode and noecho state of the connection
// Bits 0 + 1 used for TSE_NOECHO (set for noecho mode)
// Bits 2 + 3 used for TSE_SGA_CHAR (set for charmode using SGA)
// Bits 4 + 5 used for TSE_LM_CHAR (set for charmode using LINEMODE)
// each representing the state with NO, YES, WANT_NO and WANT_YES
#define Q_TSE_NOECHO ((ts[TS_EXTRA, TSE_STATE]) & 0x03)
#define S_TSE_NOECHO(y) (ts[TS_EXTRA, TSE_STATE] = \
((ts[TS_EXTRA, TSE_STATE]) & ~0x03) | (y))
#define Q_TSE_SGA_CHAR (((ts[TS_EXTRA, TSE_STATE]) & 0x0c) >> 2)
#define S_TSE_SGA_CHAR(y) (ts[TS_EXTRA, TSE_STATE] = \
((ts[TS_EXTRA, TSE_STATE]) & ~0x0c) | ((y) << 2))
#define Q_TSE_LM_CHAR (((ts[TS_EXTRA, TSE_STATE]) & 0x30) >> 4)
#define S_TSE_LM_CHAR(y) (ts[TS_EXTRA, TSE_STATE] = \
((ts[TS_EXTRA, TSE_STATE]) & ~0x30) | ((y) << 4))
#ifdef NEED_PRIVATE_PROTOTYPES
#ifndef __TELNET_H_P_PROTO__
#define __TELNET_H_P_PROTO__
private int send(int* x);
private void tel_error(string err);
private void start_telnetneg();
private string telnet_to_text(int command, int option, int* args);
private void sb_ttype(int command, int option, int* optargs);
private void sb_xdisp(int command, int option, int* optargs);
private void sb_tspeed(int command, int option, int* optargs);
private void sb_env(int command, int option, int* optargs);
private void sb_naws(int command, int option, int* optargs);
private void sb_status(int command, int option, int* optargs);
private void sb_line(int command, int option, int* optargs);
private int neg_sga(int command, int option);
private int neg_echo(int command, int option);
private int neg_bin(int command, int option);
private int neg_tm(int command, int option);
private void start_sb(int command, int option);
private void start_eor(int command, int option);
private void start_lm(int command, int option);
private void cb_echo(int command, int option);
private void cb_sga(int command, int option);
static void modify_prompt(); // std/player/prompt.c
#endif
#endif // NEED_PRIVATE_PROTOTYPES
// ************ Definitions for the TELNET protocol *************
#define IAC 255 /* interpret as command: */
#define DONT 254 /* you are not to use option */
#define DO 253 /* please, you use option */
#define WONT 252 /* I won't use option */
#define WILL 251 /* I will use option */
#define SB 250 /* interpret as subnegotiation */
#define SE 240 /* end sub negotiation */
#define EOR 239 /* end of record (transparent mode) */
#define TELCMDS ({\
"EOR", "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",\
"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC",\
})
/* backward starting with IAC == 255 */
#define TELCMD2STRING(x) (((256-x)<sizeof(TELCMDS))?TELCMDS[<(256-x)]:(""+x))
/* telnet options */
#define TELOPT_BINARY 0 /* 8-bit data path */
#define TELOPT_ECHO 1 /* echo */
#define TELOPT_RCP 2 /* prepare to reconnect */
#define TELOPT_SGA 3 /* suppress go ahead */
#define TELOPT_NAMS 4 /* approximate message size */
#define TELOPT_STATUS 5 /* give status */
#define TELOPT_TM 6 /* timing mark */
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
#define TELOPT_NAOL 8 /* negotiate about output line width */
#define TELOPT_NAOP 9 /* negotiate about output page size */
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
#define TELOPT_XASCII 17 /* extended ascic character set */
#define TELOPT_LOGOUT 18 /* force logout */
#define TELOPT_BM 19 /* byte macro */
#define TELOPT_DET 20 /* data entry terminal */
#define TELOPT_SUPDUP 21 /* supdup protocol */
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
#define TELOPT_SNDLOC 23 /* send location */
#define TELOPT_TTYPE 24 /* terminal type */
#define TELOPT_EOR 25 /* end or record */
#define TELOPT_TUID 26 /* TACACS user identification */
#define TELOPT_OUTMRK 27 /* output marking */
#define TELOPT_TTYLOC 28 /* terminal location number */
#define TELOPT_3270REGIME 29 /* 3270 regime */
#define TELOPT_X3PAD 30 /* X.3 PAD */
#define TELOPT_NAWS 31 /* window size */
#define TELOPT_TSPEED 32 /* terminal speed */
#define TELOPT_LFLOW 33 /* remote flow control */
#define TELOPT_LINEMODE 34 /* linemode negotiations */
#define TELOPT_XDISPLOC 35 /* X Display Location */
#define TELOPT_ENVIRON 36 /* Environment opt for Port ID */
#define TELOPT_AUTHENTICATION 37/* authentication */
#define TELOPT_ENCRYPT 38 /* authentication */
#define TELOPT_NEWENV 39 /* Environment opt for Port ID */
/* Inofficial, mud specific telnet options */
#define TELOPT_COMPRESS 85 /* Mud Compression Protocol, v.1 */
#define TELOPT_COMPRESS2 86 /* Mud Compression Protocol, v.2 */
#define TELOPT_MSP 90 /* Mud Sound Protocol */
#define TELOPT_MXP 91 /* Mud Extension Protocol */
#define TELOPT_EXOPL 255 /* extended-options-list */
#define NTELOPTS (1+TELOPT_NEWENV)
#define TELOPTS ({\
"BINARY", "ECHO", "RCP", "SGA", "NAME",\
"STATUS", "TM", "RCTE", "NAOL", "NAOP",\
"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",\
"NAOVTD", "NAOLFD", "XASCII", "LOGOUT", "BM",\
"DET", "SUPDUP", "SUPDUP OUTPUT",\
"SENDLOC", "TTYPE", "EOR", \
"TACACS UID", "OUTPUT MARKING", "TTYLOC",\
"3270 REGIME", "X.3 PAD", "NAWS","TSPEED","LFLOW","LINEMODE",\
"XDISPLOC","ENVIRON","AUTHENTICATION","ENCRYPT","NEWENV",\
"TELOPT 40", "TELOPT 41", "TELOPT 42", "TELOPT 43",\
"TELOPT 44", "TELOPT 45", "TELOPT 46", "TELOPT 47",\
"TELOPT 48", "TELOPT 49", "TELOPT 50", "TELOPT 51",\
"TELOPT 52", "TELOPT 53", "TELOPT 54", "TELOPT 55",\
"TELOPT 56", "TELOPT 57", "TELOPT 58", "TELOPT 59",\
"TELOPT 60", "TELOPT 61", "TELOPT 62", "TELOPT 63",\
"TELOPT 64", "TELOPT 65", "TELOPT 66", "TELOPT 67",\
"TELOPT 68", "TELOPT 69", "TELOPT 70", "TELOPT 71",\
"TELOPT 72", "TELOPT 73", "TELOPT 74", "TELOPT 75",\
"TELOPT 76", "TELOPT 77", "TELOPT 78", "TELOPT 79",\
"TELOPT 80", "TELOPT 81", "TELOPT 82", "TELOPT 83",\
"TELOPT 84", "MCCP1", "MCCP2", "TELOPT 87",\
"TELOPT 88", "TELOPT 89", "MSP", "MEP",\
})
#define TELOPT2STRING(x) ((x<sizeof(TELOPTS))?TELOPTS[x]:(""+x))
/* sub-option qualifiers */
#define TELQUAL_IS 0 /* option is... */
#define TELQUAL_SEND 1 /* send option */
#define TELQUAL_INFO 2
#define TELQUAL2STRING(x) (x<3?({"IS","SEND","INFO"})[x]:""+x)
/*
* LINEMODE suboptions
*/
#define LM_MODE 1
#define LM_FORWARDMASK 2
#define LM_SLC 3
#define MODE_EDIT 0x01
#define MODE_TRAPSIG 0x02
#define MODE_ACK 0x04
#define MODE_SOFT_TAB 0x08
#define MODE_LIT_ECHO 0x10
#define MODE_MASK (MODE_EDIT|MODE_TRAPSIG|MODE_ACK|MODE_SOFT_TAB|MODE_LIT_ECHO)
#define SLC_SYNCH 1
#define SLC_BRK 2
#define SLC_IP 3
#define SLC_AO 4
#define SLC_AYT 5
#define SLC_EOR 6
#define SLC_ABORT 7
#define SLC_EOF 8
#define SLC_SUSP 9
#define SLC_EC 10
#define SLC_EL 11
#define SLC_EW 12
#define SLC_RP 13
#define SLC_LNEXT 14
#define SLC_XON 15
#define SLC_XOFF 16
#define SLC_FORW1 17
#define SLC_FORW2 18
#define SLC_MCL 19
#define SLC_MCR 20
#define SLC_MCWL 21
#define SLC_MCWR 22
#define SLC_MCBOL 23
#define SLC_MCEOL 24
#define SLC_INSRT 25
#define SLC_OVER 26
#define SLC_ECR 27
#define SLC_EWR 28
#define SLC_EBOL 29
#define SLC_EEOL 30
#define SLC_NAMES ({"0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
"LNEXT", "XON", "XOFF", "FORW1", "FORW2", \
"MCL", "MCR", "MCWL", "MCWR", "MCBOL", "MCEOL", \
"INSRT", "OVER", "ECR", "EWR", "EBOL", "EEOL"})
#define SLC2STRING(x) ((x)<sizeof(SLC_NAMES)?SLC_NAMES[x]:sprintf("%02x",x))
#define SLC_NOSUPPORT 0
#define SLC_CANTCHANGE 1
#define SLC_VARIABLE 2
#define SLC_DEFAULT 3
#define SLC_ACK 0x80
#define SLC_FLUSHIN 0x40
#define SLC_FLUSHOUT 0x20
#define SLC_LEVELBITS 0x03
#define SLC_FLAGNAME ({ "NOSUPPORT", "CANTCHANGE", "VARIABLE", "DEFAULT" })
#define ENV_VAR 0
#define ENV_VALUE 1
#define ENV_ESC 2
#define ENV_USERVAR 3
#endif

315
mudlib/test_master.c Normal file
View File

@ -0,0 +1,315 @@
/* Test Master.c
*
* Minimal master.c to provide a very rudimentary test of the gamedriver.
* To perform the test, cd to the directory this file is in and give the
* command
* driver -N -e -m. -Mtest_master.c -s-1 -sv-1 4242
* (this assumes that you called the gamedriver 'driver' and that it is
* in your searchpath).
* Once it's running, telnet to localhost, port 4242. You should be
* connected to the driver now and be able to enter commands.
* The command 'help' will list you the commands available.
*
* A second test consists of the simple command
* driver --version
* The driver shall just print the version and exit immediately.
*/
//---------------------------------------------------------------------------
void inaugurate_master (int arg)
// Initialise the master object.
// We have to set the uid hooks, otherwise we can't clone a login object.
{
set_driver_hook(2, unbound_lambda(({}), "uid"));
set_driver_hook(3, unbound_lambda(({}), "uid"));
set_driver_hook(10, "What?\n");
#ifdef NOECHO
set_driver_hook(13, "telnetneg");
set_driver_hook(14, "set_noecho");
#endif
}
//---------------------------------------------------------------------------
int old_flag;
void set_noecho(int flag)
{
if (flag & ~old_flag & 1)
{
write("sending IAC WILL ECHO\n");
binary_message(({ 0xff, 0xfb, 0x01 })); // IAC WILL ECHO
}
else if (old_flag & ~flag & 1)
{
write("sending IAC WONT ECHO\n");
binary_message(({ 0xff, 0xfc, 0x01 })); // IAC WONT ECHO
}
if (flag & ~old_flag & 2)
{
write("sending IAC WILL+DO SGA\n");
binary_message(({ 0xff, 0xfb, 0x03 })); // IAC WILL SGA
binary_message(({ 0xff, 0xfd, 0x03 })); // IAC DO SGA
}
else if (old_flag & ~flag & 2)
{
write("sending IAC WONT+DONT SGA\n");
binary_message(({ 0xff, 0xfc, 0x03 })); // IAC WONT SGA
binary_message(({ 0xff, 0xfe, 0x03 })); // IAC DONT SGA
}
old_flag = flag;
} /* set_noecho() */
void telnetneg(int a, int b, int* c)
{
// just ignore, should work with linux telnet
printf("got %d %d %O\n", a,b,c);
}
//---------------------------------------------------------------------------
string get_simul_efun ()
// Load the simul-efun object "/sefun" if existing and return its pathname.
{
object sefun;
if (!catch(sefun = load_object("/sefun")))
return object_name(sefun);
return 0;
}
//---------------------------------------------------------------------------
string get_master_uid()
// Return the master uid.
{
return " R O O T ";
}
//---------------------------------------------------------------------------
void flag (string arg)
// Evaluate an argument given as option '-f' to the driver.
{
debug_message(sprintf("%O: flag(%O)\n", this_object(), arg));
if (arg == "test")
{
/* Insert your test code here */
return;
}
if (arg == "gc")
{
garbage_collection();
return;
}
if (arg == "dhry")
{
limited( (: load_object("dhrystone")->main(1000) :) );
shutdown();
return;
}
if (arg == "dhry2")
{
limited( (: load_object("dhrystone2")->main(1000) :) );
shutdown();
return;
}
if (arg == "shutdown")
{
shutdown();
return;
}
write ("master: Unknown flag "+arg+"\n");
}
//---------------------------------------------------------------------------
mixed prepare_destruct (object obj)
// Prepare the destruction of the object.
{
debug_message(sprintf("%O: prepare_destruct(%O)\n", this_object(), obj));
return 0;
}
//---------------------------------------------------------------------------
object connect ()
// Handle the request for a new connection.
// We simply return a clone of ourself (we can't simply return this object
// unfortunately), the gamedriver will then call logon() here.
{
object obj;
debug_message(sprintf("%O: connect()\n", this_object()));
obj = clone_object(object_name(this_object()));
return obj;
}
//---------------------------------------------------------------------------
static nomask mixed logon ()
// A connection was successfully bound to this object.
// Print some status data and add the commands.
{
debug_message(sprintf("%O: logon()\n", this_object()));
write("\nLDMud " __VERSION__ "\n\n----------\n");
write(debug_info(4,0));
write("----------\n\n");
enable_commands();
add_action("f_help", "help");
add_action("f_shutdown", "shutdown");
add_action("f_echo", "echo");
add_action("f_flag", "flag");
add_action("f_gc", "gc");
add_action("f_upd", "upd");
add_action("f_quit", "quit");
add_action("f_charmode", "charmode");
set_combine_charset("abc");
return 1; // To verify that the connection was accepted.
}
//---------------------------------------------------------------------------
int f_help (string arg)
// The 'help' command.
{
debug_message(sprintf("%O: f_help()\n", this_object()));
write(
" help - Prints this message\n"
" shutdown - shuts down the driver\n"
" flag - passes the argument to the flag() function\n"
" echo - tests the input_to() function\n"
" gc - performes a garbage collection\n"
" upd - reloads the master object\n"
" quit - terminates the connection, but leaves the driver running\n"
);
return 1;
}
//---------------------------------------------------------------------------
int f_flag (string arg)
// The 'flag' command.
{
debug_message(sprintf("%O: f_flag()\n", this_object()));
flag(arg);
return 1;
}
//---------------------------------------------------------------------------
int f_gc (string arg)
// The 'gc' command.
{
write("Requested a garbage collection.\n");
garbage_collection();
return 1;
}
//---------------------------------------------------------------------------
int f_echo (string arg)
// The 'echo' command.
{
debug_message(sprintf("%O: f_echo()\n", this_object()));
input_to("echoline", 4, "Please enter a line: ");
return 1;
}
//---------------------------------------------------------------------------
void echoline (string text)
// The user entered some text. Echo it.
{
debug_message(sprintf("%O: echoline()\n", this_object()));
write("You entered: '"+text+"'\n");
}
//---------------------------------------------------------------------------
int f_charmode (string arg)
{
write("Entering charmode. Enter 'enough' to stop.\n");
input_to("charinput", 2);
return 1;
}
string in;
void charinput(string char)
{
string cmd;
printf(" Got %O (%s)\n", char
, implode(map(to_array(char), #'to_string),","));
if (!in)
in = char;
else if (!strlen(char) || char[0] == 13)
{
cmd = in;
in = char[1..];
}
else
{
in += char;
}
if (cmd !="enough")
input_to("charinput", 2);
else
write("Ok.\n");
} /* charinput() */
//---------------------------------------------------------------------------
int f_shutdown (string arg)
// The 'shutdown' command.
{
debug_message(sprintf("%O: f_shutdown()\n", this_object()));
write("Shutting down.\n");
shutdown();
return 1;
}
//---------------------------------------------------------------------------
int f_upd (string arg)
// The 'upd' command.
{
debug_message(sprintf("%O: f_upd()\n", this_object()));
write("Removing old master...\n");
destruct(find_object(__MASTER_OBJECT__));
write("Loading master again...\n");
load_object(__MASTER_OBJECT__);
write("...done.\n");
return 1;
}
//---------------------------------------------------------------------------
int f_quit (string arg)
// The 'quit' command.
{
debug_message(sprintf("%O: f_quit()\n", this_object()));
write("Bye-bye.\n");
destruct(this_object());
return 1;
}

14
mudlib/uni-crasher/README Normal file
View File

@ -0,0 +1,14 @@
This directory holds a LPC object which runs a stress test against the driver:
it calls random efuns with random arguments and keeps a log of what has been
called.
It was written for the Unitopia mudlib (and thusly uses some of their
simul-efuns). To use it, copy secure.inc into the secure/simul_efun
directory first.
crasher.c : the test object
crashleak.c: a variant of the crasher object looking for memory leaks.
secure.inc : a replacement for the original secure/simul_efun/secure.inc,
so that the security-sensitive functions can be tested, too.
Written by Andreas "Menaures" Klauer.

View File

@ -0,0 +1,831 @@
/*
crasher: Standardversion (Menaures 07.12.01)
ANLEITUNG:
1. Bei dem Define DEBUGGER den eigenen Real-Namen angeben
2. Define VERBOSE auskommentieren, falls nicht bereits so.
VERBOSE kann genutzt werden, wenn gesicherte Dateien einen
Crash ausloesen und die genaue Zeile gesucht wird.
(VERBOSE gibt vor jedem einzelnen Aufruf momentane
Datei und Zeile per debug_message aus).
3. Wenn bereits aufgenommene Dateien existieren, das EFuns und
Values-Array NICHT modifizieren, bzw. nicht die Positionen
der einzelnen Elemente aendern - sonst werden die aufgezeichneten
Dateien unbrauchbar. Ebenso koennen nach solchen Modifikationen
aufgenommene Dateien nicht mehr von alten Versionen des Crashers
abgespielt werden.
Wer andere Values / Closures haben moechte, modifiziere die
entsprechenden Arrays, speichere den Crasher unter einem anderen
Filenamen und mache einen eindeutigen Eintrag im Header...
record:
record(file) speichert Ausfuehrungsablaeufe in Dateien namens
file_xxxx, wobei xxxx eine Durchlaufnummer ist. Das Objekt
braucht fuer diese Dateien logischerweise Schreibrecht.
Die aufgenommenen Dateien werden nach ihrer Erstellung automatisch
ausgefuehrt. Fuehrt dies zu einem Crash, kann man das ganze einfach
nochmals abspielen.
replay:
replay(file) spielt aufgenommene Dateien ab, fuehrt sie also aus.
Dies ist dazu da, um Crashes, die dieses Objekt erzeugt, zu
reproduzieren. Statt file wird file_xxxx eingelesen, wobei xxxx
eine Durchlaufnummer ist.
execute_file:
Mit execute_file(file) kann man eine Datei gezielt ausfuehren.
Dazu gibt man den echten Dateinamen der Datei an, inklusive
Durchlaufnummer.
debug_query:
Mit debug_query(file, line) kann man abfragen, was in der Datei
file in Zeile line ausgefuehrt werden wuerde - also welche
Closure mit welchen Argumenten.
Hierzu muss der eigene Name als DEBUGGER definiert sein.
debug_exec:
Mit debug_exec(file, line) wird die angegebene Zeile in der
Datei ausgefuehrt. Dadurch kann gezielt festgestellt werden,
ob der einzelne Aufruf den Crash ausgeloest hat.
Crash-Grund finden:
Bringt der Crasher den Driver zum Absturz, zunaechst den Driver
neu starten und mit execute_file das zuletzt aufgenommene File
abspielen.
Bringt das den Driver zum Crash, den gleichen Vorgang mit
aktiviertem VERBOSE wiederholen, um die Zeilennummer herauszufinden.
Hat man erst einmal die Zeilennummer, laesst sich per debug_query
herausfinden, was ausgefuehrt werden, und mit debug_exec pruefen,
ob es wirklich der Ausloeser war.
Kann der Crash auf diese Weise nicht reproduziert werden, kann man
einmal versuchen, alle aufgenommenen Dateien mit replay abzuspielen;
fuehrt das zu keinem Crash, wurde der Crash nicht durch einen
bestimmten Aufruf (oder eine bestimmte Folge selbiger) ausgeloest,
sondern hat einen anderen Grund, der genauer untersucht werden muss.
*/
#include <math.h>
#define DEBUGGER "menaures"
#include <debug.h>
// #define VERBOSE // Aktivieren, wenn man die crashausloesende Zeile sucht
#define MAX_ARGS 5
#define DELAY 4
#define ITERATIONS 1000
mixed execute;
mixed efuns;
mixed values;
mixed names;
void record(string file);
void reset_all()
{
catch(
execute = 0,
( efuns =
({
#'Name,
#'[,
#'abs,
#'abs_path,
#'acos,
#'add_action,
#'add_dot_to_msg,
// #'add_verb,
// #'add_xverb,
#'all_environment,
#'all_inventory,
#'allocate,
// #'allocate_mapping,
#'and_bits,
#'apply,
#'arr_delete,
#'asin,
// #'assoc,
#'atan,
#'atan2,
#'attach_erq_demon,
#'auto_owner_search,
#'binary_message,
#'bind_lambda,
// #'break_point,
#'call_other,
#'call_out,
#'call_out_info,
#'call_resolved,
#'caller_stack,
#'caller_stack_depth,
#'capitalize,
#'cat,
#'catch,
#'ceil,
#'center,
#'clear_bit,
#'clock,
#'clone_object,
#'clonep,
// #'clones,
#'closurep,
#'command,
#'command_stack,
#'command_stack_depth,
#'cond_present,
#'convert_message,
#'convert_umlaute,
#'copies,
#'copy,
#'copy_bits,
#'copy_file,
// #'copy_mapping,
#'cos,
#'count_bits,
#'crypt,
#'ctime,
// #'db_affected_rows,
// #'db_close,
// #'db_coldefs,
// #'db_connect,
// #'db_conv_string,
// #'db_error,
// #'db_exec,
// #'db_fetch,
// #'db_handles,
// #'db_insert_id,
#'debug_info,
#'debug_message,
#'deep_copy,
#'deep_inventory,
#'deep_present,
#'dein,
#'deinem,
#'deinen,
#'deines,
#'dem,
#'den,
#'der,
#'des,
#'destruct,
#'diesem,
#'diesen,
#'dieser,
#'dieses,
#'disable_commands,
#'domain2map,
#'ed,
// #'efun308,
#'ein,
#'einem,
#'einen,
#'eines,
#'enable_commands,
#'environment,
#'er,
#'exec,
#'execute_command,
#'exp,
#'expand_define,
#'explode,
#'export_uid,
#'extern_call,
// #'extract,
// #'file_name,
#'file_path,
#'file_size,
#'file_time,
#'filter,
// #'filter_array,
#'filter_indices,
// #'filter_mapping,
#'filter_objects,
#'find_call_out,
#'find_living,
#'find_object,
#'find_player,
#'first_inventory,
#'floatp,
#'floor,
#'format_seconds,
#'format_vseconds,
#'funcall,
#'function_exists,
#'functionlist,
#'garbage_collection,
#'get_align_string,
#'get_dir,
#'get_error_file,
#'get_eval_cost,
#'get_extra_wizinfo,
#'get_genitiv,
#'get_type_info,
#'get_unique_string,
#'geteuid,
#'getuid,
#'gmtime,
#'heart_beat_info,
#'ihm,
#'ihn,
#'ihr,
#'ihrem,
#'ihren,
#'ihres,
#'implode,
#'inherit_list,
#'input_to,
// #'insert_alist,
#'interactive,
// #'intersect_alist,
#'intp,
#'invert_bits,
#'ist,
#'lambda,
#'last_bit,
#'last_instructions,
#'left,
#'limited,
#'liste,
#'living,
#'load_name,
#'load_object,
#'localtime,
#'log,
#'log_file,
#'lower_case,
#'m_allocate,
#'m_contains,
#'m_delete,
#'m_indices,
#'m_reallocate,
// #'m_sizeof,
#'m_values,
#'make_shared_string,
#'map,
#'map2domain,
// #'map_array,
#'map_indices,
// #'map_mapping,
#'map_object,
#'map_objects,
// #'mapping_contains,
#'mappingp,
#'max,
#'md5,
#'member,
// #'member_array,
#'min,
#'mixed2str,
#'mixed_to_closure,
#'mkdir,
#'mkmapping,
#'move_object,
#'negate,
#'next_bit,
#'next_inventory,
#'not_alone,
#'notify_fail,
#'object_info,
#'object_name,
#'object_time,
#'objectp,
#'or_bits,
// #'order_alist,
#'parse_com,
#'parse_com_error,
#'parse_com_error_string,
#'player_exists,
#'player_present,
#'playerp,
#'plural,
#'pointerp,
#'pol2xy,
#'pow,
#'present,
#'present_clone,
#'previous_object,
#'printf,
#'process_string,
#'program_name,
#'program_time,
#'query_actions,
// #'query_akkusativ,
#'query_command,
// #'query_dativ,
#'query_deklin,
#'query_deklin_adjektiv,
#'query_deklin_ein_adjektiv,
#'query_deklin_name,
// #'query_dekliniert,
#'query_editing,
// #'query_genitiv,
#'query_idle,
// #'query_imp_port,
#'query_input_pending,
#'query_ip_name,
#'query_ip_number,
#'query_limits,
#'query_living_name,
#'query_livings,
#'query_load_average,
#'query_mud_port,
#'query_notify_fail,
#'query_once_interactive,
#'query_pronom,
#'query_real_player_level,
#'query_shadowing,
#'query_snoop,
#'query_udp_port,
#'query_up_time,
#'query_verb,
#'quote,
#'raise_error,
#'random,
#'read_bytes,
#'read_file,
#'real_time_diff,
#'referencep,
#'regexp,
#'regexplode,
#'regreplace,
#'remove_action,
#'remove_call_out,
#'remove_input_to,
#'remove_interactive,
#'rename,
#'rename_object,
#'replace_program,
#'restore_object,
#'restore_value,
#'right,
#'rm,
#'rmdir,
#'round,
#'rusage,
#'save_object,
#'save_value,
#'say,
#'search_object,
#'sein,
#'seinem,
#'seinen,
#'seines,
#'send_erq,
// #'send_imp,
#'send_udp,
// #'set_auto_include_string,
#'set_bit,
#'set_buffer_size,
#'set_combine_charset,
#'set_connection_charset,
#'set_driver_hook,
#'set_environment,
#'set_extra_wizinfo,
#'set_extra_wizinfo_size,
#'set_heart_beat,
#'set_is_wizard,
#'set_light,
#'set_limits,
#'set_living_name,
#'set_modify_command,
#'set_next_reset,
#'set_prompt,
#'set_this_object,
#'set_this_player,
#'seteuid,
#'sgn,
#'shadow,
#'short_format_seconds,
#'short_format_vseconds,
#'shorttimestr,
#'shortvtimestr,
#'shout,
#'shutdown,
#'sin,
#'sizeof,
// #'slice_array,
#'snoop,
#'sort_array,
#'space,
#'sprintf,
#'sqrt,
#'sscanf,
#'str2int,
#'string_parser,
#'stringp,
#'strip,
#'strlen,
#'strstr,
#'substr,
// #'swap,
#'symbol_function,
#'symbol_variable,
#'symbolp,
#'sys_log,
#'tail,
#'tan,
#'tell_object,
#'tell_room,
#'terminal_colour,
#'test_bit,
#'this_interactive,
#'this_object,
#'this_player,
#'throw,
#'time,
#'time_to_vtime,
#'timestr,
#'to_array,
#'to_float,
#'to_int,
#'to_object,
#'to_string,
#'touch,
#'trace,
#'traceprefix,
#'transpose_array,
#'trim,
#'typeof,
#'unbound_lambda,
#'unique_array,
#'unmkmapping,
#'unshadow,
#'upper_case,
#'users,
#'utime,
#'vclock,
#'vtime,
#'vtime_to_time,
#'vtimestr,
#'walk_mapping,
#'wem,
#'wen,
#'wer,
#'wessen,
#'widthof,
#'wizardshellp,
#'wizlist_info,
#'wrap,
#'wrap_say,
#'write,
#'write_bytes,
#'write_file,
#'xor_bits,
#'xy2pol,
#',,
#'=,
#'+=,
#'-=,
#'&=,
#'|=,
#'^=,
#'<<=,
#'>>=,
#'>>>=,
#'*=,
#'%=,
#'/=,
#'?,
#'||,
#'&&,
#'|,
#'^,
#'&,
#'==,
#'!=,
#'>,
#'>=,
#'<,
#'<=,
#'<<,
#'>>,
#'>>>,
#'+,
#'-,
#'*,
#'%,
#'/,
#'++,
#'--,
#'negate,
#'!,
#'~,
#'({,
#'([,
#'[,
#'[<,
#'[..],
#'[..<],
#'[<..],
#'[<..<],
#'[..,
#'[<..,
#'({,
#'([,
}) ),
( values =
({
/* --- Integers: --- */
0,
1,
-1,
32,
-32,
40,
-40,
29292929,
-5050211,
__INT_MAX__,
__INT_MIN__,
/* --- Floats: --- */
0.0,
0.5,
-0.5,
55.5,
-55.5,
999999999999999999999999999999999999999999999.99,
-999999999999999999999999999999999999999999999.99,
/* --- Strings: --- */
"",
"foo bar",
"%d %q %T",
"0",
"",
" ",
"_",
"^^^^^^",
"#^# #^#",
" ^",
"^ ",
" - - - - ",
"? ? ? ? ? ? ????? ???? ??",
"°°°°°°°°°°°°°°°°°°°°°",
"\\/ "*32,
" !"*42,
/* --- Objekte: --- */
touch("/obj/fackel"),
touch("/obj/rucksack"),
touch("/obj/rope"),
touch("/secure/master"),
clone_object("/obj/schiff"),
clone_object("/obj/player"),
clone_object("/obj/tisch"),
/* --- Closures: --- */
(: :),
(: (: 1 :) :),
#'sizeof,
#'garbage_collection,
symbol_function("query_long", touch("/i/item")),
lambda( ({'x, 'y}), ({#'?, ({#'>, 'x, 'y}), 'x, 'y}) ),
unbound_lambda( ({'x}), ({#'==, 0, 'x}) ),
/* --- Arrays: --- */
({ }),
({ 0 }),
({ "" }),
({ ({ }) }),
({ ([ ]) }),
allocate(3000),
/* --- Mappings: --- */
([ ]),
([ (: :) ]),
m_allocate(5,5),
mkmapping(allocate(30), allocate(30, ({})), allocate(30, (:1:))),
}) )
); // catch
if(pointerp(values)) {
values += ({0,0,0});
apply((: values[<3] = $1 :), &execute);
apply((: values[<2] = $1 :), &values);
apply((: values[<1] = $1 :), &efuns);
}
while(remove_call_out("execute_file") != -1);
while(remove_call_out("do_replay") != -1);
while(remove_call_out("do_record") != -1);
seteuid(getuid());
}
int execute_file(string file)
{
int line;
string str;
mixed restore;
if(!stringp(file) || file_size(file) <= 0)
{
DEBUG("ERROR: Cannot execute "+file+": Invalid file.");
return 0;
}
DEBUG("Executing: "+file);
for(line = 0; (str=read_file(file, line, 2)) && strlen(str); line += 2)
{
restore = restore_value(str);
rm("/save/crash/LAST_EXEC");
write_file("/save/crash/LAST_EXEC",
save_value( ({file, line}) ));
#ifdef VERBOSE
debug_message("File: "+file+" Line: "+line+"\n");
#endif
debug_message(sprintf("REPLAY: %O %O -> %O %O\n", restore[0], restore[1], efuns[ restore[0] ], map( restore[1], (: values[$1] :) )));
catch(
apply( efuns[ restore[0] ],
map( restore[1], (: values[$1] :) ) )
);
}
return 1;
}
mixed query_values() { return values; }
int generate_file(string file)
{
int i, h, efun_index, * value_index;
if(!stringp(file) || !write_file(file, ""))
{
DEBUG("ERROR: Cannot write file: "+file);
debug_message(wrap("ERROR: Cannot write file: "+file));
seteuid(getuid());
record("/save/crash/"+(mixed2str(utime())-"({,})"));
return 0;
}
DEBUG("Recording: "+file);
for(i = ITERATIONS; i--; )
{
efun_index = random(sizeof(efuns));
value_index = ({});
for(h = random(MAX_ARGS+1); h--; )
{
value_index += ({ random(sizeof(values)) });
}
write_file(file, save_value( ({efun_index, value_index}) ));
}
return 1;
}
void replay(string file)
{
if (!file)
{
file = names[0];
names = names[1..];
}
DEBUG("Stopping all actions and starting REPLAY for: "+file);
reset_all();
execute = ({ #'call_out, "do_replay", DELAY, file, 1 });
// Um this_player etc. loszuwerden einen Reset-Hack ;o)
set_next_reset(DELAY);
}
static void do_replay(string file, int number)
{
if(execute_file(file + right(number, 5, "_0000")))
{
call_out("do_replay", DELAY, file, number+1);
}
else call_out("replay", DELAY, 0);
}
void record(string file)
{
DEBUG("Stopping all actions and starting RECORD for: "+file);
reset_all();
execute = ({ #'call_out, "do_record", DELAY, file, 1 });
// Um this_player etc. loszuwerden einen Reset-Hack ;o)
set_next_reset(DELAY);
}
static void do_record(string file, int number)
{
if(generate_file(file+right(number, 5, "_0000")))
{
call_out("execute_file", DELAY, file+right(number, 5, "_0000"));
call_out("do_record", DELAY*2, file, number+1);
}
}
void reset()
{
// Um this_player etc. loszuwerden einen Reset-Hack ;o)
if(execute)
{
apply(execute[0], execute[1..]);
execute = 0;
}
}
void debug_query(string file, int line)
{
mixed restore;
restore = restore_value(read_file(file, line, 2));
rm("/save/crash/TEMP");
write_file("/save/crash/TEMP",
sprintf("apply( %Q, %Q )", efuns[ restore[0] ],
map(restore[1], (: values[$1] :))));
({this_player()})->more("/save/crash/TEMP");
}
void debug_exec(string file, int line)
{
mixed restore;
restore = restore_value(read_file(file, line, 2));
catch(
apply( efuns[ restore[0] ], map(restore[1], (: values[$1] :)))
);
}
void create()
{
string str;
mixed strs;
reset_all();
str = read_file("/save/crash/LAST_EXEC");
if(str)
{
catch( apply( #'debug_query, restore_value(str) ),
write_file("/save/crash/CRASHERS",
"-"*80 + "\n"
+ read_file("/save/crash/TEMP")+ "\n" ) );
}
#if 0
strs = get_dir("/save/crash/1*");
foreach(str : strs)
{
rm("/save/crash/"+str);
}
#endif
#if 1
call_out("record", 4, "/save/crash/"+(mixed2str(utime())-"({,})"));
#else
names = ({
"/save/crash/crash1"
});
call_out("replay", 4, 0);
#endif
}
/* --- End of file. --- */

View File

@ -0,0 +1,686 @@
// This is for crash purposes only. Don't run it in a production MUD.
//
// It may still depend on some UNItopia stuff, I haven't tested it with other
// libs. If you're using the UNItopia Mudlib to run it, you have to remove all
// nomask simul efuns (empty the file /secure/simul_efun/secure.inc), and
// unlock all privilege violations in /secure/master/compiler_control.inc by
// adding return 1; of the function.
//
// ------------------------------------------------------------------
// File: crashleak.c
// Description: Try to crash the driver and/or find memory leaks
// by calling EFuns and Operators with random arguments.
// Based on my old crasher.c
// Author: Menaures@UNItopia (2004-07-17)
//
/* --- Documentation: --- */
/* --- Inherits: --- */
/* --- Includes: --- */
#include <rtlimits.h>
// Replace this with some kind of output if you
// want Debug-Messages
#define DEBUG(x) {}
/* --- Defines: --- */
// Undef the following if you're not interested in Memleaks
#define FIND_MEMORY_LEAKS
// Where shall we write our data to?
#define CRASHLEAK_DIR "/save/crashleak/"
// Where is the doc/efun directory of the driver package?
#define DOC_EFUN_DIR CRASHLEAK_DIR"doc/efun/"
#define FILE(x,y) (CRASHLEAK_DIR+l_time+"_"+sprintf("%'0'6d_%s", (y), (x)))
#define GC_FILE(x) FILE("GC_"+(x), ++filecounter)
#define RECORD_FILE(x) FILE("REC_"+(x), ++filecounter)
#define LEAK_FILE(x) FILE("LEAK_"+(x), ++filecounter)
#define LOG_FILE(x) FILE("LOG_"+(x), ++filecounter)
// How many calls shall we do per step?
#define CALLS_PER_STEP 1000
// How long to wait between steps?
// Careful, Memleak detection might not work for lower values!
#define STEP_PAUSE 4
// Sometimes objects get removed out of the values array.
// Do you want to reinitialize it every X steps?
// For maximum Memleak Find reliability, set to 1,
// which causes reinitialization in every step (halfing
// the speed)
#define REINIT_EVERY_N_STEPS 10
// This defines minimum and maximum number of arguments per
// function call. Recorded files may still be executed with
// old values if you change this.
#define MIN_PARAMS 0
#define MAX_PARAMS 15
// NOTE:
// When looking for Memleaks, only one step per PAUSE will be made.
// Thus, detecting all Memleaks of one real step will require
// a minimum of CALLS_PER_STEP*STEP_PAUSE time until the next step
// is done with full stress speed again. This is probably a long
// time, however: if there are few leaks, lower CALLS_PER_STEP
// will only add up to the time it takes to find one in the first
// place...
/* --- Global Variables: --- */
int l_time = time(); // Just as a unique number...
mixed * efun; // EFun- and Operator-Closures. Either #'foo or ({#'foo, min_param, max_param})
mixed * value; // Value-set which contains all Data Types.
int stepcounter; // For reinit after N steps.
int filecounter; // For file naming.
mixed * queue; // Queue, to have one call-out-loop instead of many
#ifdef FIND_MEMORY_LEAKS
mixed * leakage; // To track GCs and Execs for Leak detection.
#endif
/* --- Prototypes: --- */
void crash(string file, closure callback);
void leak(closure callback);
#ifdef FIND_MEMORY_LEAKS
void check_for_leak(string file, mixed * exec);
void step_by_step(string gc_file, string file, mixed * exec);
#endif
/* --- Functions: --- */
/* --- Queue --- */
// Basic Queue, mainly to prevent recursion problems.
// And to make call_out loops easier (we have more than one)
mixed * query_queue() { return queue; }
int push(int pos, varargs mixed * what)
{
if(!pointerp(queue))
{
queue = ({});
}
if(pos <= 0)
{
pos = sizeof(queue) + 1;
}
queue = queue[0..pos-2] + ({ what }) + queue[pos-1..];
}
int pop()
{
mixed q;
if(pointerp(queue) && sizeof(queue))
{
q = queue[0];
queue = queue[1..];
apply(q[0],q[1..]);
return sizeof(queue);
}
}
void step()
{
if(set_next_reset(0) > 300)
{
set_next_reset(150);
}
pop();
call_out(#'step, STEP_PAUSE);
}
/* --- Crashleak Initialization: --- */
// Just to provide some LFun Closures below...
string foo() { return "foo"; }
mixed bar(mixed x, mixed y, mixed z) { return ({z,y,x}); }
mixed query_efun() { return efun; }
void init_efun()
{
DEBUG("init_efun()");
// Generate list of all EFuns. /doc/efun/ is part of the driver package.
// If it isn't part of your mudlib directory, copy it somewhere in it
// and modify the path accordingly.
string * list = get_dir(DOC_EFUN_DIR"*") - ({".","..","[]"});
// Convert them to EFun closures using a restore_value hack.
efun = restore_value("#1:0\n({#e:"+implode(list, ",#e:")+",})\n");
// Kill unrecognized and dangerous EFuns.
efun -= ({0,
#'efun::set_driver_hook, // it makes the crasher stop running
#'efun::limited, // too much fun
#'efun::set_this_object, // poses problems
#'efun::garbage_collection, // Can't find no leaks otherwise
#'efun::shutdown, // Can't find no crashes otherwise
#'efun::set_limits}); // Messes things up naturally
// Add Operator closures. Have not found a way to generate this list
// automatically yet, so you might want to check if it's still up2date.
// See lex.c ~ approx line 1000 for a list (this one's of 2004/07/17).
efun +=
({ #'+= ,#'++ ,#'+ ,#'-= ,#'-- ,#'- ,#'*= ,#'* ,#'/=
,#'/ ,#'%= ,#'% ,#', ,#'^= ,#'^ ,#'|| ,#'||= ,#'|=
,#'| ,#'&& ,#'&&= ,#'&= ,#'& ,#'~ ,#'<= ,#'<<= ,#'<<
,#'< ,#'>= ,#'>>= ,#'>>>= ,#'>>> ,#'>> ,#'> ,#'== ,#'=
,#'!= ,#'! ,#'?! ,#'? ,#'[..] ,#'[..<] ,#'[<..]
,#'[<..<] ,#'[..>] ,#'[>..] ,#'[<..>]
,#'[>..<] ,#'[>..>] ,#'[.. ,#'[<..
,#'[>.. ,#'[,] ,#'[ ,#'[< ,#'[>
,#'({ ,#'([ ,#'-> ,#'(<
});
}
mixed query_values() { return value; }
struct Bar {
mixed four;
};
struct Foo {
int one, *two;
struct Bar three;
};
void init_value()
{
DEBUG("init_value()");
// The more values, the more variation, the better.
// Feel free to add stuff to this list. However, don't modify it
// on the fly, changing this array will make recorded files useless.
// Please refrain from using self-referencing structures unless you
// want to test the crash aspect only. Include self-referencing
// stuff inside #ifndef FIND_MEMORY_LEAKS #endif blocks only.
if(pointerp(value))
{
// Do some cleanup first:
map(value, (: objectp($1) && destruct($1) :));
}
value = 0;
value =
({
/* --- Integer: --- */
-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
-1000,1000,-50000,50000,-2000000,2000000,
__INT_MIN__+16,__INT_MAX__-16,__INT_MIN__,__INT_MAX__,
/* --- Float: --- */
0.0,0.001,-0.001,-0.5,0.5,0.99,-0.99,1.01,-1.01,
42.767,-42.767,1.0,2.0,3.0,-1.0,-2.0,-3.0,
to_float(__INT_MIN__), to_float(__INT_MAX__),
1.0e+100, -1.0e+100,
/* --- String: --- */
"", " ", " ", "!_!_", "_!_!",
"foo","bar","foo bar", "%d", "%Q", "0", "^^^^^^",
"#^# #^#", " ^",
"^ ", " - - - - ",
"? ? ? ? ? ? ????? ???? ??", "",
"\\/ "*32, " !"*42, "/", "/..",
"/a", "/d/", "/w/..",
"%#Q%#Q%#Q","%d%-=80s%%",
save_value(efun), save_object(),
/* --- Object: --- */
// This is mudlib specific, please provide some objects;
// Preferred are Blueprints, Clones, Objects with Environment,
// and Objects which have other objects inside (rooms).
//
// Note that random calls (for example to destruct()) might
// remove objects; so they should be reloaded here.
// A proper cleanup of old objects then would probably be good too.
load_object("/obj/fackel"), clone_object("/obj/fackel"),
load_object("/obj/player"), clone_object("/obj/player"),
load_object("/i/item/message"),
clone_object("/obj/rucksack"), clone_object("/obj/kurstafel"),
clone_object("/obj/wizard_shell"), clone_object("/secure/obj/login"),
load_object("/secure/obj/login"), load_object("/apps/error_db"),
load_object("/apps/plugin"), clone_object("/obj/zauberstab"),
load_object("/room/church"), load_object("/room/void"),
load_object("/room/hell"), load_object("/room/death/death"),
load_object("/room/rathaus/treppe"),
load_object("/room/rathaus/konferenz"),
load_object("/room/rathaus/forum"),
clone_object("/obj/monster"), clone_object("/obj/monster"),
clone_object("/obj/monster"), clone_object("/obj/monster"),
/* --- Closure: --- */
(: :), (: 1 :), (: 0 :), (: $2/$1 :),
#'efun::max, #'efun::input_to, #'efun::this_player,
#'efun::this_object, #'efun::call_out,
symbol_function("query_long", load_object("/i/item")),
symbol_function("query_real_name", load_object("/i/player/player")),
#'foo, #'bar,
function { return 2 * $1; },
function int (int a) { return 2 * a; },
function (int a) { return 2 * a; },
lambda( ({'x, 'y}), ({#'?, ({#'>, 'x, 'y}), 'x, 'y}) ),
unbound_lambda( ({'x}), ({#'==, 0, 'x}) ),
(: for(;;); :), (: while($1); :),
/* --- Array: --- */
({}), ({ ({}) }), ({ (: :) }), ({ 0 }), ({ 1 }),
({ "" }), ({ ([]) }), ({#'efun::min}),
allocate(5), allocate(10,1), allocate(query_limits(1)[LIMIT_ARRAY]),
({'x, 'y}), ({#'?, ({#'>, 'x, 'y}), 'x, 'y}),
({'x}), ({#'==, 0, 'x}),
/* --- Mapping: --- */
([:0]), ([:1]), ([:2]), (["a":"b"]),([([1]):({2,3})]),
mkmapping( ({1,2,3,4,5,6,7,8,9,10}), ({1,2,3,4,5,6,7,8,9,10}) ),
mkmapping( ({"1","2","3","4","5","6","7","8","9","10"}) ),
([ load_object("/apps/groups") ]),
([ #'efun::allocate ]),
/* --- Symbol / Quoted: --- */
'a, 'b, 'c, quote(allocate(10)),
'dont_know_what_this_is_supposed_to_be_it_sure_is_fun,
'whatever_floats_your_boat,
/* --- Struct: --- */
});
// --- Lets add some special values. ---
// Container inside Container inside...
object ob = clone_object("/obj/rucksack");
for(int i = 10; i--; )
{
object ob2 = clone_object("/obj/rucksack");
ob->move(ob2);
ob=ob2;
}
value += ({ob});
// Some random strings. Good for crashing, bad for debugging...
// So to make things reproducible, we generate them only once,
// and only load them afterwards. Delete the Savefile if you
// want new random strings.
string str;
if(str = read_file(CRASHLEAK_DIR"random_strings.o"))
{
value += restore_value(str);
}
else
{
string * random_strings = ({});
for(int i = 10; i--; )
{
int * arr;
arr = map(allocate(random(100)), (: random(256) :));
random_strings += ({ to_string(arr) });
}
// Save these strings so that we can reuse them next time.
write_file(CRASHLEAK_DIR"random_strings.o",
save_value(random_strings));
// Don't forget to add them to the values array...
value += random_strings;
}
// Structs
struct Bar foo = (<Bar> 10);
struct Foo bar = (<Foo> 1, ({"2",3}), (<Bar> 5));
value += ({foo,bar})*20;
}
mixed do_plot_efun(closure cl)
{
// DEBUG(sprintf("do_plot_efun(%#Q)",cl));
object ob = this_object();
int min_p = MIN_PARAMS;
int max_p = MAX_PARAMS;
for(int p = MAX_PARAMS; p >= MIN_PARAMS; p--)
{
string str = catch(apply(cl, allocate(p)); nolog);
// DEBUG(sprintf(" str -> %#Q", str));
if(str && strstr(str, "many arguments") != -1)
{
max_p--;
}
else if(str && strstr(str, "few arguments") != -1)
{
min_p++;
}
}
set_this_object(ob);
seteuid(0);
seteuid(getuid());
if(min_p != MIN_PARAMS || max_p != MAX_PARAMS)
{
return ({cl, min_p, max_p});
}
return cl;
}
void plot_efun()
{
DEBUG("plot_efun()");
efun = filter(efun, #'closurep);
efun = limited(#'map, ({10000000}), efun, #'do_plot_efun);
garbage_collection(GC_FILE("plot_efun"));
}
void init_crashleak(closure callback)
{
DEBUG("init_crashleak()");
// Sometimes init fails. Recall.
push(1, #'init_crashleak, callback);
string str;
if(str = catch(limited(#'init_efun, ({1000000})); publish))
{
debug_message("CRASHLEAK: init_efun failed:\n"+str+"\n");
return;
}
if(str = catch(limited(#'init_value, ({1000000})); publish))
{
debug_message("CRASHLEAK: init_value failed:\n"+str+"\n");
}
garbage_collection(GC_FILE("AFTER_INIT"));
// Del the old entry
queue = queue[1..];
push(0, callback);
// Determine EFun parameter counts next step.
push(1, #'plot_efun);
}
void crashleak()
{
DEBUG("crashleak()");
if(stepcounter++ == REINIT_EVERY_N_STEPS)
{
init_crashleak(#'crashleak);
stepcounter=0;
return;
}
#ifdef FIND_MEMORY_LEAKS
push(0, #'crash, RECORD_FILE("cl"), #'check_for_leak);
#else
push(0, #'crash, RECORD_FILE("cl"), #'crashleak);
#endif
}
/* --- Crash Execution: --- */
mixed * pick()
{
DEBUG("pick()");
mixed * erg = ({});
int f, p;
for(int i = CALLS_PER_STEP; i--; )
{
f = random(sizeof(efun));
if(closurep(efun[f]))
{
p = MIN_PARAMS + random(MAX_PARAMS-MIN_PARAMS);
}
else
{
p = efun[f][1] + random(efun[f][2]-efun[f][1]);
}
erg +=
({
// Pick EFun index.
({ random(sizeof(efun)),
// Pick p parameter indices.
map(allocate(p), (: random(sizeof(value)) :)),
// Will be replaced with a string later:
// (debugmessage of what was executed)
0
})
});
}
return erg;
}
varargs void exec(mixed * exec, int quiet)
{
DEBUG("exec()");
string file;
string text = "";
object ob = this_object();
debug_message("start_of_exec\n");
foreach(mixed * x : exec)
{
mixed f = efun[x[0]];
if(pointerp(f)) f=f[0];
mixed * v = map(x[1], (: value[$1] :));
string str = sprintf("%d %#Q\n", x[0],x[1]);
// Note: This chance affects arrays by reference. :-)
x[2] = str;
debug_message(sprintf("exec: %s",str));
set_this_object(ob);
seteuid(0);
seteuid(getuid());
catch(apply(f, v); reserve (max(get_eval_cost()/2,100000)), nolog);
if(get_eval_cost() < 100000)
{
break;
}
}
set_this_object(ob);
debug_message("end_of_exec\n");;
}
void crash(string file, closure callback)
{
DEBUG("crash()");
mixed * exec;
/* --- Pick what we will execute in this run: --- */
exec = limited(#'pick, ({1000000}));
/* --- Record it to the file. --- */
write_file(file, save_value(exec));
/* --- Execute it. --- */
limited(#'exec, ({1000000}), exec);
funcall(callback, file, exec);
}
/* --- Leak detection: --- */
int analyze(string gc_file)
{
DEBUG("analyze("+gc_file+")");
string s = read_file(gc_file);
if(!stringp(s))
{
debug_message(sprintf("CRASHLEAK: Could not read file %#Q (%#Q)!\n",gc_file,s));
return 0;
}
string * str = explode(s, "\n");
return sizeof(regexp(str, "freeing.*block"));
}
void leak_gc(string file, mixed * exec)
{
DEBUG("leak_gc( ["+sizeof(exec)+"] )");
string sbs = GC_FILE("sbs");
// GC.
garbage_collection(sbs);
// Note this file will be created later.
// Push.
push(1, #'step_by_step, sbs, file, exec);
// Execute.
limited(#'exec, ({1000000}), exec, 1);
}
void step_by_step(string gc_file, string file, mixed * exec)
{
DEBUG("step_by_step()");
// Okay. Binary search.
// Was there a leak?
if(analyze(gc_file))
{
// Whee! There was one. Let's see what we do.
// How many execs are there which might have caused the leak?
if(sizeof(exec) == 1)
{
// Only one? Okay, this is it then.
DEBUG("LEAK: "+exec[0][2]+"\n");
write_file(LEAK_FILE(explode(gc_file,"/")[<1]), exec[0][2]+"\n");
// We haven't done a GC, so we can pop:
call_out(#'pop, 0);
return;
}
// Okay. Do the first half now...
leak_gc(file, exec[..(sizeof(exec)/2)-1]);
// ...push the second half into the first queue, coz we can't do
// to garbage_collection() at once.
push(1, #'leak_gc, file, exec[(sizeof(exec)/2)..]);
}
else
{
// We haven't done a GC, so we can pop:
call_out(#'pop, 0);
}
// And wait...
}
void check_for_leak(string file, mixed * exec)
{
DEBUG("check_for_leak()");
string gc_file = GC_FILE("check_for_leak");
// Warning: This is actually executed at the end of the cycle,
// and not right now.
garbage_collection(gc_file);
// This means gc_file does not exist now yet.
// Check previous leakage (their gc_file exists now)
if(leakage && analyze(leakage[0]))
{
// We need to do a step by step further investigation
// of this exec to find which call exactly has caused
// the leak.
push(0, #'step_by_step, leakage[0], leakage[1], leakage[2]);
// Continue Crashing afterwards.
push(0, #'crashleak);
}
else
{
// nothing to do. continue crashing.
crashleak();
}
// Remember this leakage and test it in the next run.
leakage = ({gc_file,file,exec});
}
/* --- Applied LFuns: --- */
void reset()
{
if(sizeof(queue) <= 0)
{
push(0, #'init_crashleak, #'crashleak);
}
if(find_call_out(#'step) <= 0)
{
call_out(#'step, STEP_PAUSE);
}
}
void create()
{
DEBUG("create()");
garbage_collection(GC_FILE("AFTER_CREATE"));
reset();
}
/* --- End of file. --- */

View File

@ -0,0 +1,152 @@
// This file is part of UNItopia Mudlib.
// ----------------------------------------------------------------
// File: /secure/simul_efun/secure.inc
// Description: Security Funktionen / Gesperrte Funktionen
// Author: Freaky
// Modified by: Freaky (31.03.1999) set_environment, object_info hinzugefuegt
// Freaky (26.06.1999) command hinzugefuegt
//
// $Log: secure.inc,v $
// Revision 1.1.1.1 2006/07/10 02:42:07 lynx
// ldmud 3.3.714
//
// Revision 1.3 2001/01/30 23:59:01 sissi
// Bergeweise CVS Log Eintraege eingetragen.
// Hoffentlich nirgends doppelt und nirgends zu wenig.
//
#pragma strict_types
#pragma save_types
//
// Dieser File ist der einizge Teil der Simul Efun mit
// nomask simul_efun Privileg.
// (siehe /secure/master/compiler_control::privilege_violation())
//
/*
* Nur der Shutdown-Daemon darf die efun shutdown verwenden!
*/
#if 0
/*
* Gesperrte efuns
*/
#if __EFUN_DEFINED__(shutdown)
nomask void shutdown() {}
#endif
/*
#if __EFUN_DEFINED__(set_next_reset)
nomask int set_next_reset(int delay) {}
#endif
*/
#if __EFUN_DEFINED__(heart_beat_info)
nomask object *heart_beat_info() {}
#endif
#if __EFUN_DEFINED__(object_info)
nomask mixed *object_info(object ob, int what) {}
#endif
#if __EFUN_DEFINED__(debug_info)
nomask varargs mixed debug_info(int flag, mixed m) {}
#endif
#if __EFUN_DEFINED__(move_object)
nomask void move_object(object ob1, object ob2) {}
#endif
#if __EFUN_DEFINED__(set_this_player)
nomask void set_this_player(object ob) {}
#endif
#if __EFUN_DEFINED__(set_environment)
nomask void set_environment(object ob1, object ob2) {}
#endif
#if __EFUN_DEFINED__(efun308)
nomask void efun308(object ob1, object ob2) {}
#endif
#if __EFUN_DEFINED__(swap)
nomask void swap(object ob) {}
#endif
#if __EFUN_DEFINED__(break_point)
nomask void break_point() {}
#endif
#if __EFUN_DEFINED__(functionlist)
nomask mixed *functionlist(mixed ob, int flag) {}
#endif
#if __EFUN_DEFINED__(query_actions)
nomask mixed *query_actions(mixed ob, mixed flag) {}
#endif
#if __EFUN_DEFINED__(garbage_collection)
nomask void garbage_collection() {}
#endif
#if __EFUN_DEFINED__(command)
nomask int command(string str) {}
#endif
#if __EFUN_DEFINED__(last_instructions)
nomask varargs string *last_instructions(int len, int verbose) {}
#endif
#if __EFUN_DEFINED__(command_stack)
nomask mixed *command_stack() {}
#endif
#if __EFUN_DEFINED__(command_stack_depth)
nomask int command_stack_depth() {}
#endif
#if __EFUN_DEFINED__(set_buffer_size)
nomask int set_buffer_size(int size) {}
#endif
/*
#if __EFUN_DEFINED__(restore_value)
nomask mixed restore_value(string str) {}
#endif
#if __EFUN_DEFINED__(save_value)
nomask string save_value(mixed m) {}
#endif
*/
/*
#if __EFUN_DEFINED__(clones)
nomask varargs object *clones(mixed m, int i) {}
#endif
*/
#if __EFUN_DEFINED__(set_connection_charset)
nomask void set_connection_charset(mixed a, int i) {}
#endif
#if __EFUN_DEFINED__(binary_message)
nomask varargs int binary_message(mixed m, int i) {}
#endif
#if __EFUN_DEFINED__(query_ip_number)
nomask varargs string query_ip_number(object who)
{
return "0.0.0.0";
}
#endif
#if __EFUN_DEFINED__(query_ip_name)
nomask varargs string query_ip_name(object who)
{
return "leider.nicht.mehr.verfuegbar";
}
#endif
#endif

332
psyclpc.1 Normal file
View File

@ -0,0 +1,332 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
.TH PSYCLPC "1" "April 2007" "psyclpc 4.0.0 - a multi-protocol network server application language." "User Commands"
.SH NAME
psyclpc \- psyclpc
.SH SYNOPSIS
.B psyclpc
[\fIoptions\fR] [\fI<portnumber>\fR...]
.SH DESCRIPTION
psyclpc 4.0.0 \- a multi\-protocol network server application language.
.PP
Release: Build 1.5 (mostly stable); 2007\-04\-17
Compiled: Apr 17 2007 15:39:05
.PP
Options are:
.HP
\fB\-\-args\fR <filename>
.IP
Read the options from <filename> as if they were given on the
commandline.
.HP
\fB\-P\fR|\-\-inherit <fd\-number>
.IP
Inherit filedescriptor <fd\-number> from the parent process
as socket to listen for connections.
.HP
\fB\-u\fR|\-\-udp <portnumber>
.IP
Specify the <portnumber> for the UDP port, overriding the compiled\-in
default.
.HP
\fB\-D\fR|\-\-define <macro>[=<text>]
.IP
Add <macro> (optionally to be expanded to <text>) to the list of
predefined macros known by the LPC compiler.
.HP
\fB\-E\fR|\-\-eval\-cost <ticks>
.IP
Set the number of <ticks> available for one evaluation thread.
.HP
\fB\-M\fR|\-\-master <filename>
.IP
Use <filename> for the master object.
.HP
\fB\-m\fR|\-\-mudlib <pathname>
.IP
Use <pathname> as the top directory of the mudlib.
.HP
\fB\-\-debug\-file\fR <filename>
.IP
Log all debug output in <filename> instead of <host>.debug.log .
.HP
\fB\-\-hostname\fR <name>
.IP
Use <name> as hostname, instead of what the system says.
.HP
\fB\-\-hostaddr\fR <addr>
.IP
Use <addr> as address of this machine, instead of what the
system says. In particular this address will be used to open
the driver ports.
.HP
\fB\-\-compat\fR
.HP
\fB\-\-no\-compat\fR
.IP
Select the mode (compat or plain) of the driver.
Note that this choice does not affect the default name of the master
object.
.HP
\fB\-d\fR|\-\-debug
.IP
Generate debug output; repeat the argument for even more output.
.HP
\fB\-c\fR|\-\-list\-compiles
.IP
List the name of every compiled file on stderr.
.HP
\fB\-e\fR|\-\-no\-preload
.IP
Pass a non\-zero argument (the number of occurences of this option)
to master\->preload(), which usually inhibits all preloads of castles
and other objects.
.HP
\fB\-\-erq\fR <filename>
.HP
\fB\-\-erq\fR "<filename> <erq arguments>"
.IP
Use <filename> instead of 'erq' as the name of the ERQ executable.
If the name starts with a '/', it is take to be an absolute pathname,
otherwise it is interpreted relative to /opt/psyced/bin.
If not specified, 'erq' is used as executable name.
With the proper use of quotes it is legal to pass arbitrary arguments
to the erq, however, these may not contain spaces themselves.
.HP
\fB\-N\fR|\-\-no\-erq
.IP
Don't start the erq demon (if it would be started at all).
.HP
\fB\-\-alarm\-time\fR <time>
.IP
The granularity of call_out()s and heartbeats (minimum: 1).
.HP
\fB\-\-heart\-interval\fR <time>
.IP
The time to elapse between two heartbeats (minimum: 1).
.HP
\fB\-\-sync\-heart\fR
.IP
All heartbeats are executed at the same time (modulo granularity).
.HP
\fB\-\-async\-heart\fR
.IP
Heartbeats are executed immediately when they are due (modulo granularity).
.HP
\fB\-t\fR|\-\-no\-heart
.IP
Disable heartbeats and call_outs.
.HP
\fB\-f\fR|\-\-funcall <word>
.IP
The lfun master\->flag() is called with <word> as argument before the
gamedriver accepts network connections.
.HP
\fB\-\-cleanup\-time\fR <time>
.IP
The idle time in seconds for an object before the driver tries to
clean it up. This time should be substantially higher than the
reset time. A time <= 0 disables the cleanup mechanism.
.HP
\fB\-\-reset\-time\fR <time>
.IP
The time in seconds for an object before it is reset.
A time <= 0 disables the reset mechanism.
.HP
\fB\-\-regexp\fR pcre|traditional
.IP
Select the default regexp package.
.HP
\fB\-\-max\-array\fR <size>
.IP
The maximum number of elements an array can hold.
Set to 0, arrays of any size are allowed.
.HP
\fB\-\-max\-callouts\fR <number>
.IP
The maximum number of callouts at one time.
Set to 0, any number of callouts is allowed.
.HP
\fB\-\-max\-mapping\fR <size>
.IP
The maximum number of elements (keys+values) a mapping can hold.
Set to 0, mappings of any size are allowed.
.HP
\fB\-\-max\-mapping\-keys\fR <size>
.IP
The maximum number of entries (keys) a mapping can hold.
Set to 0, mappings of any size are allowed.
.HP
\fB\-\-max\-bytes\fR <size>
.IP
The maximum number of bytes one read_bytes()/write_bytes() call
can handle.
Set to 0, reads and writes of any size are allowed.
.HP
\fB\-\-max\-file\fR <size>
.IP
The maximum number of bytes one read_file()/write_file() call
can handle.
Set to 0, reads and writes of any size are allowed.
.HP
\fB\-\-max\-thread\-pending\fR <size>
.IP
The maximum number of bytes to be kept pending by the socket write
thread.
Set to 0, an unlimited amount of data can be kept pending.
(Ignored since pthreads are not supported)
.TP
\fB\-s\fR <time>
| \fB\-\-swap\-time\fR <time>
.HP
\fB\-s\fR v<time> | \fB\-\-swap\-variables\fR <time>
.IP
Time in seconds before an object (or its variables) are swapped out.
A time less or equal 0 disables swapping.
.HP
\fB\-s\fR f<name> | \fB\-\-swap\-file\fR <name>
.IP
Swap into file <name> instead of log/ldmud.swap.<host> .
.HP
\fB\-s\fR c | \fB\-\-swap\-compact\fR
.IP
Reuse free space in the swap file immediately.
.HP
\fB\-\-max\-malloc\fR <size>
.IP
Restrict total memory allocations to <size> bytes. A <size> of 0
or 'unlimited' removes any restriction.
.HP
\fB\-\-min\-malloc\fR <size>
.HP
\fB\-\-min\-small\-malloc\fR <size>
.IP
Determine the sizes for the explicite initial large resp. small chunk
allocation. A size of 0 disables the explicite initial allocations.
.HP
\fB\-r\fR u<size> | \fB\-\-reserve\-user\fR <size>
.HP
\fB\-r\fR m<size> | \fB\-\-reserve\-master\fR <size>
.HP
\fB\-r\fR s<size> | \fB\-\-reserve\-system\fR <size>
.IP
Reserve <size> amount of memory for user/master/system allocations to
be held until main memory runs out.
.HP
\fB\-\-filename\-spaces\fR
.HP
\fB\-\-no\-filename\-spaces\fR
.IP
Allow/disallow the use of spaces in filenames.
.HP
\fB\-\-strict\-euids\fR
.HP
\fB\-\-no\-strict\-euids\fR
.IP
Enforce/don't enforce the proper use of euids.
.HP
\fB\-\-share\-variables\fR
.HP
\fB\-\-init\-variables\fR
.IP
Select how clones initialize their variables:
.IP
\- by sharing the current values of their blueprint
\- by initializing them afresh (using __INIT()).
.HP
\fB\-\-tls\-key\fR <pathname>
.IP
Use <pathname> as the x509 keyfile, default is 'key.pem'.
If relative, <pathname> is interpreted relative to <mudlib>.
.HP
\fB\-\-tls\-cert\fR <pathname>
.IP
Use <pathname> as the x509 certfile, default is 'cert.pem'.
If relative, <pathname> is interpreted relative to <mudlib>.
.IP
Use <pathname> as the filename holding your trusted PEM certificates.
If relative, <pathname> is interpreted relative to <mudlib>.
.IP
Use <pathname> as the directory where your trusted PEM certificates reside,
default is '/etc/ssl/certs'.
If relative, <pathname> is interpreted relative to <mudlib>.
.IP
Use <pathname> as the filename holding your certificate revocation lists.
If relative, <pathname> is interpreted relative to <mudlib>.
.IP
Use <pathname> as the directory where your certificate revocation lists reside.
If relative, <pathname> is interpreted relative to <mudlib>.
.HP
\fB\-\-wizlist\-file\fR <filename>
.HP
\fB\-\-no\-wizlist\-file\fR
.IP
Read and save the wizlist in the named file (always interpreted
relative the mudlib); resp. don't read or save the wizlist.
.HP
\fB\-\-pidfile\fR <filename>
.IP
Write the pid of the driver process into <filename>.
.HP
\fB\-\-random\-seed\fR <num>
.IP
Seed value for the random number generator. If not given, the
driver chooses a seed value on its own.
.HP
\fB\-\-gcollect\-outfd\fR <filename>|<num>
.IP
Garbage collector output (like a log of all reclaimed memory blocks)
is sent to <filename> (or inherited fd <num>) instead of stderr.
.HP
\fB\-\-check\-refcounts\fR
.IP
Every backend cycle, all refcounts in the system are checked.
SLOW!
.HP
\fB\-\-check\-state\fR <lvl>
.IP
Perform a regular simplistic check of the virtual machine according
to <lvl>:
.IP
= 0: no check
= 1: once per backend loop
= 2: at various points in the backend loop
.HP
\fB\-\-gobble\-descriptors\fR <num>
.IP
<num> (more) filedescriptors are used up. You'll know when you need it.
.HP
\fB\-\-options\fR
.IP
Print the version and compilation options of the driver, then exit.
.HP
\fB\-V\fR|\-\-version
.IP
Print the version of the driver, then exit.
.HP
\fB\-\-longhelp\fR
.IP
Display this help and exit.
.HP
\fB\-h\fR|\-?|\-\-help
.IP
Display the short help text and exit.
.PP
Release: Build 1.5 (mostly stable); 2007\-04\-17
Compiled: Apr 17 2007 15:39:05
.SH CONTACT
psyclpc is being maintained by fippo & lynX.
fippo is available at psyc://goodadvice.pages.de/~fippo
or xmpp:fippo@goodadvice.pages.de
lynX is available as psyc://psyced.org/~lynx
You can reach us at psyc://psyced.org/@welcome
.SH HISTORY
psyclpc, an LDMud with a couple of patches and optimization for psyced,
available from <http://lpc.psyc.eu>.
LDMud itself is a continuation of the Amylaar LPMud Gamedriver 3.1.2.
See also <http://www.bearnip.com/lars/proj/ldmud.html>.
psyclpc is released under the GNU LIBRARY GENERAL PUBLIC LICENSE, Version 2.

81
src/C_COMPILER_BUGS Normal file
View File

@ -0,0 +1,81 @@
gcc version 2.9-aix51-020209:
make_func.y::read_func_spec() a too large fprintf() statement
causes the compiler to generated faulty code on the assignment which
causes the mkfunc program to crash. Splitting the print statement
into two solved the problem.
Visual Age C 6.0, AIX 5.2:
make_func.y::read_func_spec() the particularly sized fprintf() statement
causes the compiler to generated faulty code on the following assignment,
which in turn causes the mkfunc program to generate faulty data. Splitting
the print statement into two solved the problem.
gcc 2.9, 3.2 - Cygwin
Highest optimization creates buggy code when the total size of local
variables gets too big (>= 8KBytes).
gcc 3.0
Optimization option -funroll-all-loops seems to create buggy code.
gcc 2.91.66 19990314/Linux (egcs-1.1.2) on Linux/x86:
Computing MIN_LONG % -1 causes a floating point exception.
xlc on AIX 3.4:
Optimization level -O4 -qipa crashes in the code generation if a void
returning function is casted to a value returning one.
egcs 2.91.66 on Linux 2.2.15 on Sun SparcStation4:
The optimizer neglects to reload CPU registers after a setjmp() in
complex functions (namely eval_instruction() in interpret.c). The
workaround is to put the setjmp()-recover branch into a separate function
and making sure that it can't be inlined (e.g. by calling it indirectly).
gcc 2.8.1 on Solaris 5.7; egcs 2.91.16 on SunOS 4.1.3_U1, and probably
others:
Compiling with optimization causes the compiler (not the assembler!) to
fall into catatonia for the configuration test for a float/branch
incompatibility. Workaround is to make sure that configure compiles this
test without optimization.
gcc 2.9-beos-980929 on BeOS/x86:
Compiling without optimization causes the compiler to crash on simulate.c
gcc 2.7.2.1-i486-linux on Linux 2.0.33:
Optimizing compiles may pessimize the expression
(svalue.type == x && svalue.x.closure_type == y)
to 'comparison is always zero' if both fields share the same longword
in memory (closure.c is one victim).
Makeshift solution: Assigning one of the fields to a local variable
causes the expression to produce the correct result.
gcc 1.36 on Next / NextStep 2.1 with flags '-g' / '-g -fomit_frame_pointer' :
The calculated offset to a6 for parameter access in free_svalue() is wrong.
Symptom: mud crashes early.
Makeshift solution: use '-O -fomit-frame-pointer'
gcc 2.2.2 , when told to optimize interpret.c , usually dies with a segv
or currupted internal data structures in cc1.
gcc 2.3.3 , when told to optimize lex.c , will garble the code for #include.
Symptom: load_object will fail when #include is used, saying it can't
#include the file.
gcc 2.x on 680x0 hardware: the large interpret.c switch table is built with
unsigned short words, but is processed like signed short words.
The special thing about 680x0 is that the switch in interpret.c is
shorter than 64 KB.
Symptoms: when LPC instructions are to be executed the code to which
lies beyond the first 32 KB of the switch(), there is weird behaviour,
a C-level illegal intruction or a crash with undetermined, although most
times quite short, latency.
Makeshift solution: fix the assembler code in interpret.s to handle
unsigned short offsets.
NeXTStep 3.2 has a broken memcmp(), that will give different return values
depending on alignment.
The library that contained this broken memcmp() looks like this:
-r-xr-xr-x 1 root 1012100 Sep 1 1993 libsys_s.B.shlib*
quickfix: #define memcmp(a,b,l) (*(int*)(a) - *(int*)(b)) in closure.c and
prolang.y, or a file included by these.
ULTRIX dec1 4.3 0 RISC needs <sys/types.h> to be included before <sys/stat.h>

619
src/Makefile.in Normal file
View File

@ -0,0 +1,619 @@
# TODO: Add some of the symbols in here to configure
# These lines are needed on some machines.
MAKE=make
SHELL=@CONFIG_SHELL@
INSTALL=@INSTALL@
mkinstalldirs=$(SHELL) @top_srcdir@/mkinstalldirs
#
CC=@CC@
#
YACC = @YACC@
YACCTAB = @YACCTAB@
#
RM = rm -f
MV = mv
CP = cp
#
# some standard stuff...
prefix= @prefix@
exec_prefix= @exec_prefix@
# currently unused:
datarootdir = @datarootdir@
#
#
# Set MUD_LIB to the directory which contains the mud data.
MUD_LIB = @libdir@
# Set MUD_LIB_INCLUDE to the directory where the driver include files
# shall live.
MUD_LIB_INCLUDE = @includedir@
#
# Set BINDIR to the directory where you want to install the executables.
BINDIR = @bindir@
#
# Set ERQ_DIR to directory which contains the stuff which ERQ can
# execute (hopefully) savely. Was formerly defined in config.h!
ERQ_DIR= @libexecdir@
#
# Set MANDIR to the directory where to install the manpages.
MANDIR= @mandir@
#
# Typical profiling, warning and optimizing options.
# -p -DMARK: together they enable customized profiling of VM instructions.
# MARK needs to be defined to a statement taking the
# instruction code as parameter; additionally interpret.c will
# #include "profile.h" for additional custom declarations.
#
# Additional profiling can be activated in config.h .
#PROFIL=-pg -DMARK
#PROFIL=-pg
PROFIL=
# Enable warnings from the compiler, if wanted.
NO_WARN= # no warning options - will work with all compilers :-)
GCC_WARN= -Wall -Wshadow -Wparentheses # gcc settings
CFG_WARN= @WCFLAGS@ # Warn options discovered by configure
WARN= $(CFG_WARN)
# Optimization and source level debugging options.
# adding a -fomit-frame-pointer on the NeXT (gcc version 1.93 (68k, MIT syntax))
# will corrupt the driver.
HIGH_OPTIMIZE = @OCFLAGS@ # high optimization
MED_OPTIMIZE= @MCFLAGS@ # medium optimization
LOW_OPTIMIZE = @LCFLAGS@ # minimal optimization
NO_OPTIMIZE= @DCFLAGS@ # no optimization; for frequent recompilations.
OPTIMIZE= $(@val_optimize@_OPTIMIZE)
#
# Debugging options:
# Debugging options should be set in config.h to guarantee a clean
# recompile.
#DEBUG = -DDEBUG # -DDEBUG_TELNET
DEBUG=
#
MPATH=-DMUD_LIB='"$(MUD_LIB)"' -DBINDIR='"$(BINDIR)"' -DERQ_DIR='"$(ERQ_DIR)"'
#
CFLAGS=-DPROGNAME='"@PROGNAME@"' @EXTRA_CFLAGS@ $(OPTIMIZE) $(DEBUG) $(WARN) $(MPATH) $(PROFIL)
#
LIBS=@LIBS@ @PKGLIBS@
#
LDFLAGS=$(PROFIL) @LDFLAGS@
#
#Note that, if you use smalloc with SBRK_OK(which is the default), and
#don't link statically, it could happen that the system malloc is linked
#along with the one from smalloc; this combination is bound to cause crashes.
MFLAGS = "BINDIR=$(BINDIR)" "MUD_LIB=$(MUD_LIB)"
#
SRC = access_check.c actions.c array.c backend.c bitstrings.c call_out.c \
closure.c comm.c \
dumpstat.c ed.c efuns.c files.c gcollect.c hash.c heartbeat.c \
interpret.c \
lex.c main.c mapping.c md5.c mempools.c mregex.c mstrings.c object.c \
otable.c\
parser.c parse.c pkg-alists.c pkg-idna.c \
pkg-mccp.c pkg-mysql.c pkg-pcre.c \
pkg-pgsql.c pkg-sqlite.c pkg-tls.c \
ptmalloc.c port.c ptrtable.c \
random.c regexp.c sha1.c simulate.c simul_efun.c stdstrings.c \
strfuns.c structs.c sprintf.c swap.c wiz_list.c xalloc.c pkg-expat.c
OBJ = access_check.o actions.o array.o backend.o bitstrings.o call_out.o \
closure.o comm.o \
dumpstat.o ed.o efuns.o files.o gcollect.o hash.o heartbeat.o \
interpret.o \
lex.o main.o mapping.o md5.o mempools.o mregex.o mstrings.o object.o \
otable.o \
parser.o parse.o pkg-alists.o pkg-idna.o \
pkg-mccp.o pkg-mysql.o pkg-pcre.o \
pkg-pgsql.o pkg-sqlite.o pkg-tls.o \
ptmalloc.o port.o ptrtable.o \
random.o regexp.o sha1.o simulate.o simul_efun.o stdstrings.o \
strfuns.o structs.o sprintf.o swap.o wiz_list.o xalloc.o @ALLOCA@ \
pkg-expat.o
all: make-patchlevel @PROGNAME@@EXEEXT@
@PROGNAME@@EXEEXT@: $(OBJ)
$(CC) @OPTIMIZE_LINKING@ $(LDFLAGS) $(OBJ) -o $@ $(LIBS)
it: @PROGNAME@@EXEEXT@
strip @PROGNAME@@EXEEXT@
docs: @PROGNAME@@EXEEXT@
-help2man --name=@PROGNAME@ -N --help-option=--longhelp --include=../HELP --output=../@PROGNAME@.1 ./@PROGNAME@@EXEEXT@
install-all: install-driver install-headers install-utils
install: install-driver
@echo "To install header files, use 'make install-headers'."
@echo "To install utility programs (incl. erq), use 'make install-utils'."
@echo "To install everything in one go, use 'make install-all'."
install-driver: @PROGNAME@@EXEEXT@ docs
$(mkinstalldirs) $(BINDIR) $(MANDIR)/man1
$(INSTALL) -c @PROGNAME@@EXEEXT@ $(BINDIR)/@PROGNAME@@EXEEXT@
$(INSTALL) -c ../doc/man/@PROGNAME@.1 $(MANDIR)/man1/@PROGNAME@.1
install-headers:
$(mkinstalldirs) $(MUD_LIB_INCLUDE)
$(INSTALL) -c ../mudlib/sys/* $(MUD_LIB_INCLUDE)
install-utils:
(cd util; $(MAKE) $(MFLAGS) install)
utils:
(cd util; $(MAKE) $(MFLAGS))
lint: *.c
lint *.c
clean:
$(RM) $(YACCTAB)h $(YACCTAB)c make_func.c *.o mkfunc@EXEEXT@
$(RM) dftables@EXEEXT@ pcre/chartables.c
$(RM) stdstrings.c stdstrings.h
$(RM) efun_defs.c instrs.h lang.y lang.h lang.c y.output tags TAGS
$(RM) @PROGNAME@@EXEEXT@ core mudlib/core mudlib/debug.log
(cd util ; echo "Cleaning in util." ; $(MAKE) clean)
distclean: clean
$(RM) @PROGNAME@@EXEEXT@ config.status machine.h Makefile config.cache config.log
$(RM) config.h config.status config.status.old
$(RM) util/Makefile util/erq/Makefile
tags: $(SRC)
ctags $(SRC)
TAGS: $(SRC)
etags $(SRC)
patchlevel.h : make-patchlevel
make-patchlevel:
./mk-patchlevel.sh
make_func.c: make_func.y
$(YACC) make_func.y
@MOVE_YACC_TAB@ make_func.c
@CLEAN_YACC_TAB@
#mkfunc.o : mkfunc.c make_func.c driver.h config.h machine.h port.h
# $(CC) $(CFLAGS) -c mkfunc.c
mkfunc@EXEEXT@: mkfunc.o hash.o exec.h
$(CC) @OPTIMIZE_LINKING@ $(LDFLAGS) mkfunc.o hash.o -o mkfunc@EXEEXT@
dftables.o : pcre/dftables.c pcre/maketables.c pcre/config.h
$(CC) $(CFLAGS) -c pcre/dftables.c -o dftables.o
dftables@EXEEXT@ : dftables.o
$(CC) @OPTIMIZE_LINKING@ $(LDFLAGS) dftables.o -o dftables@EXEEXT@
lang.y: mkfunc@EXEEXT@ prolang.y config.h
$(RM) lang.y
./mkfunc@EXEEXT@ lang
efun_defs.c instrs.h: func_spec mkfunc@EXEEXT@ config.h machine.h
$(RM) instrs.h
$(RM) efun_defs.c
./mkfunc@EXEEXT@ instrs
stdstrings.c stdstrings.h: string_spec mkfunc@EXEEXT@ config.h machine.h
$(RM) stdstrings.c
$(RM) stdstrings.h
./mkfunc@EXEEXT@ strings
lang.c lang.h: lang.y
$(YACC) -d -v lang.y
@MOVE_YACC_TAB@ lang.c
@CLEAN_YACC_TAB@
$(MV) $(YACCTAB)h lang.h
pcre/chartables.c : dftables@EXEEXT@
./dftables@EXEEXT@ pcre/chartables.c
#--------------------------------------------------------
# The dependency generation uses the program 'mkdepend' and assumes GNUmake.
# Generated source files (overlaps with of SRC) which need to be
# present for mkdepend to work.
GENSRC = make_func.c stdstrings.c lang.c instrs.h pcre/chartables.c
# Macros for MkDepend:
SKELETON = $(SRC) mkfunc.c pcre/dftables.c
EXCEPT = -x efun_defs.c
SELECT = -S instrs.h -S stdstrings.h -S make_func.c -S lang.c -S lang.h -S efun_defs.c
depend: $(SRC) $(GENSRC)
@$(SHELL) -ec "if type mkdepend > /dev/null 2>&1; then \
echo Updating dependencies.; \
mkdepend $(SKELETON) -I. $(EXCEPT) -m -p .c:%n.o -fMakefile; \
mkdepend $(SKELETON) -I. $(EXCEPT) $(SELECT) -m -p .c:%n.o -fMakefile; \
echo Updating dependencies in Makefile.in.; \
mkdepend $(SKELETON) -I. $(EXCEPT) -m -p .c:%n.o -fMakefile.in; \
mkdepend $(SKELETON) -I. $(EXCEPT) $(SELECT) -m -p .c:%n.o -fMakefile.in; \
else\
echo mkdepend utility not available.; \
fi"
.PHONY dependall: depend depend-generic
depend-generic: $(SRC) $(GENSRC)
@$(SHELL) -ec "if type mkdepend > /dev/null 2>&1; then \
echo Updating dependencies in hosts/be/Makefile.; \
mkdepend $(SKELETON) -I. $(EXCEPT) -m -p .c:$$\(OBJ\)/%n.o -fhosts/be/Makefile; \
mkdepend $(SKELETON) -I. $(EXCEPT) $(SELECT) -m -p .c:$$\(OBJ\)/%n.o -fhosts/be/Makefile; \
else\
echo mkdepend utility not available.; \
fi"
#--------------------------------------------------------
# Dependencies, manual and automatic.
# --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS FOLLOW ---
access_check.o : xalloc.h filestat.h comm.h access_check.h driver.h \
svalue.h strfuns.h pkg-tls.h simulate.h typedefs.h config.h port.h \
sent.h bytecode.h hosts/unix.h hosts/be/be.h machine.h
actions.o : ../mudlib/sys/driver_hook.h ../mudlib/sys/commands.h xalloc.h \
wiz_list.h svalue.h simulate.h sent.h stdstrings.h object.h mstrings.h \
mapping.h interpret.h efuns.h dumpstat.h comm.h closure.h backend.h \
array.h actions.h my-alloca.h typedefs.h driver.h strfuns.h bytecode.h \
hash.h pkg-tls.h main.h port.h config.h hosts/unix.h hosts/be/be.h \
machine.h
array.o : i-svalue_cmp.h xalloc.h wiz_list.h swap.h svalue.h simulate.h \
stdstrings.h object.h mstrings.h mempools.h mapping.h main.h \
interpret.h closure.h backend.h array.h my-alloca.h typedefs.h driver.h \
strfuns.h sent.h bytecode.h hash.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
backend.o : ../mudlib/sys/debug_message.h ../mudlib/sys/driver_hook.h \
xalloc.h wiz_list.h swap.h svalue.h stdstrings.h simulate.h random.h \
otable.h object.h mstrings.h mregex.h mapping.h main.h lex.h \
interpret.h heartbeat.h gcollect.h filestat.h exec.h ed.h comm.h \
closure.h call_out.h array.h actions.h backend.h my-alloca.h typedefs.h \
driver.h strfuns.h sent.h bytecode.h hash.h pkg-tls.h port.h config.h \
hosts/unix.h hosts/be/be.h machine.h
bitstrings.o : xalloc.h svalue.h simulate.h mstrings.h interpret.h \
bitstrings.h typedefs.h driver.h strfuns.h sent.h bytecode.h hash.h \
backend.h port.h config.h main.h hosts/unix.h hosts/be/be.h machine.h
call_out.o : ../mudlib/sys/debug_info.h xalloc.h wiz_list.h swap.h svalue.h \
strfuns.h stdstrings.h simulate.h object.h mstrings.h main.h \
interpret.h gcollect.h exec.h comm.h closure.h backend.h array.h \
actions.h call_out.h typedefs.h driver.h sent.h bytecode.h hash.h \
pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
closure.o : i-svalue_cmp.h xalloc.h switch.h swap.h svalue.h structs.h \
stdstrings.h simul_efun.h simulate.h prolang.h object.h mstrings.h \
main.h lex.h interpret.h instrs.h exec.h backend.h array.h closure.h \
my-alloca.h typedefs.h driver.h strfuns.h hash.h ptrtable.h sent.h \
bytecode.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
comm.o : util/erq/erq.h ../mudlib/sys/input_to.h \
../mudlib/sys/driver_hook.h ../mudlib/sys/comm.h xalloc.h wiz_list.h \
swap.h svalue.h stdstrings.h simulate.h sent.h pkg-tls.h pkg-pgsql.h \
pkg-mccp.h object.h mstrings.h main.h interpret.h gcollect.h filestat.h \
exec.h ed.h closure.h array.h actions.h access_check.h comm.h \
../mudlib/sys/telnet.h my-alloca.h typedefs.h driver.h strfuns.h \
bytecode.h hash.h backend.h config.h port.h hosts/unix.h hosts/be/be.h \
machine.h
dumpstat.o : xalloc.h svalue.h structs.h stdstrings.h simulate.h ptrtable.h \
object.h mstrings.h mapping.h instrs.h filestat.h exec.h closure.h \
array.h dumpstat.h typedefs.h driver.h strfuns.h hash.h sent.h \
bytecode.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
ed.o : ../mudlib/sys/regexp.h xalloc.h svalue.h stdstrings.h simulate.h \
object.h mstrings.h mregex.h main.h lex.h interpret.h gcollect.h \
filestat.h comm.h actions.h ed.h typedefs.h driver.h strfuns.h sent.h \
bytecode.h hash.h backend.h pkg-tls.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
efuns.o : ../mudlib/sys/time.h ../mudlib/sys/strings.h \
../mudlib/sys/regexp.h ../mudlib/sys/objectinfo.h \
../mudlib/sys/driver_hook.h ../mudlib/sys/debug_info.h xalloc.h \
wiz_list.h svalue.h swap.h structs.h strfuns.h simulate.h stdstrings.h \
sha1.h random.h ptrtable.h otable.h object.h mstrings.h mregex.h md5.h \
mempools.h mapping.h main.h lex.h interpret.h heartbeat.h exec.h \
dumpstat.h comm.h closure.h call_out.h backend.h array.h actions.h \
efuns.h my-rusage.h my-alloca.h typedefs.h driver.h hash.h sent.h \
bytecode.h my-stdint.h pkg-tls.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
files.o : ../mudlib/sys/files.h xalloc.h svalue.h stdstrings.h simulate.h \
mstrings.h mempools.h main.h lex.h interpret.h filestat.h comm.h \
array.h files.h my-alloca.h typedefs.h driver.h strfuns.h sent.h \
bytecode.h hash.h backend.h pkg-tls.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
gcollect.o : ../mudlib/sys/driver_hook.h xalloc.h wiz_list.h swap.h \
structs.h stdstrings.h simul_efun.h simulate.h sent.h random.h \
ptrtable.h prolang.h pkg-pgsql.h parse.h otable.h object.h mstrings.h \
mregex.h mempools.h mapping.h main.h lex.h instrs.h interpret.h \
heartbeat.h filestat.h ed.h comm.h closure.h call_out.h backend.h \
array.h actions.h gcollect.h typedefs.h driver.h svalue.h strfuns.h \
hash.h exec.h bytecode.h pkg-tls.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
hash.o : hash.h
heartbeat.o : ../mudlib/sys/debug_info.h xalloc.h wiz_list.h svalue.h \
strfuns.h simulate.h sent.h object.h mstrings.h interpret.h gcollect.h \
exec.h comm.h backend.h array.h actions.h heartbeat.h typedefs.h \
driver.h bytecode.h hash.h pkg-tls.h main.h port.h config.h \
hosts/unix.h hosts/be/be.h machine.h
interpret.o : ../mudlib/sys/trace.h ../mudlib/sys/debug_info.h \
../mudlib/sys/driver_hook.h xalloc.h wiz_list.h switch.h swap.h \
svalue.h structs.h stdstrings.h simul_efun.h simulate.h prolang.h \
parse.h otable.h object.h mstrings.h mapping.h lex.h instrs.h \
heartbeat.h gcollect.h filestat.h exec.h efuns.h ed.h comm.h closure.h \
call_out.h backend.h array.h actions.h interpret.h my-alloca.h \
typedefs.h driver.h strfuns.h hash.h ptrtable.h sent.h bytecode.h \
pkg-tls.h main.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
lex.o : efun_defs.c ../mudlib/sys/driver_hook.h xalloc.h wiz_list.h \
svalue.h strfuns.h stdstrings.h simul_efun.h simulate.h prolang.h \
patchlevel.h object.h mstrings.h mempools.h main.h lang.h interpret.h \
instrs.h hash.h gcollect.h filestat.h exec.h comm.h closure.h backend.h \
array.h lex.h my-alloca.h typedefs.h driver.h ptrtable.h sent.h \
bytecode.h pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h \
machine.h
main.o : ../mudlib/sys/regexp.h pkg-mysql.h xalloc.h wiz_list.h swap.h \
svalue.h stdstrings.h simul_efun.h simulate.h random.h pkg-tls.h \
patchlevel.h otable.h object.h mstrings.h mregex.h mempools.h mapping.h \
lex.h interpret.h gcollect.h filestat.h comm.h array.h backend.h main.h \
my-alloca.h typedefs.h driver.h strfuns.h ptrtable.h exec.h sent.h \
bytecode.h hash.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
mapping.o : i-svalue_cmp.h xalloc.h wiz_list.h svalue.h structs.h \
simulate.h object.h mstrings.h main.h interpret.h gcollect.h closure.h \
backend.h array.h mapping.h my-alloca.h typedefs.h driver.h strfuns.h \
hash.h exec.h sent.h bytecode.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
md5.o : strfuns.h md5.h machine.h typedefs.h driver.h port.h config.h \
hosts/unix.h hosts/be/be.h
mempools.o : ../mudlib/sys/debug_info.h xalloc.h svalue.h strfuns.h \
simulate.h gcollect.h mempools.h driver.h typedefs.h sent.h bytecode.h \
port.h config.h hosts/unix.h hosts/be/be.h machine.h
mkfunc.o : make_func.c ../mudlib/sys/driver_hook.h hash.h exec.h \
my-alloca.h driver.h bytecode.h typedefs.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
mregex.o : ../mudlib/sys/regexp.h ../mudlib/sys/driver_hook.h \
../mudlib/sys/debug_info.h xalloc.h svalue.h strfuns.h simulate.h \
regexp.h pkg-pcre.h mstrings.h main.h interpret.h hash.h gcollect.h \
comm.h mregex.h driver.h typedefs.h sent.h bytecode.h pcre/pcre.h \
backend.h pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h \
machine.h
mstrings.o : ../mudlib/sys/debug_info.h xalloc.h svalue.h strfuns.h \
stdstrings.h simulate.h main.h hash.h gcollect.h mstrings.h driver.h \
typedefs.h sent.h bytecode.h port.h config.h hosts/unix.h hosts/be/be.h \
machine.h
object.o : ../mudlib/sys/inherit_list.h ../mudlib/sys/include_list.h \
../mudlib/sys/functionlist.h ../mudlib/sys/driver_hook.h xalloc.h \
wiz_list.h svalue.h swap.h structs.h strfuns.h stdstrings.h \
simul_efun.h simulate.h sent.h random.h ptrtable.h prolang.h otable.h \
mstrings.h mempools.h mapping.h main.h lex.h instrs.h interpret.h \
filestat.h comm.h closure.h backend.h array.h actions.h object.h \
my-alloca.h typedefs.h driver.h ../mudlib/sys/lpctypes.h hash.h exec.h \
bytecode.h pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h \
machine.h
otable.o : ../mudlib/sys/debug_info.h xalloc.h svalue.h simulate.h \
strfuns.h object.h mstrings.h hash.h gcollect.h backend.h otable.h \
typedefs.h driver.h sent.h bytecode.h main.h port.h config.h \
hosts/unix.h hosts/be/be.h machine.h
parse.o : xalloc.h wiz_list.h svalue.h stdstrings.h simulate.h object.h \
mstrings.h main.h lex.h interpret.h gcollect.h array.h actions.h \
parse.h typedefs.h driver.h strfuns.h sent.h bytecode.h hash.h \
backend.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
parser.o : lang.c ../mudlib/sys/driver_hook.h xalloc.h wiz_list.h switch.h \
swap.h svalue.h structs.h stdstrings.h simul_efun.h simulate.h object.h \
mstrings.h mapping.h main.h lex.h instrs.h interpret.h gcollect.h \
exec.h closure.h backend.h array.h prolang.h my-alloca.h typedefs.h \
driver.h strfuns.h hash.h ptrtable.h sent.h bytecode.h port.h config.h \
hosts/unix.h hosts/be/be.h machine.h
dftables.o : pcre/maketables.c pcre/internal.h pcre/pcre.h pcre/config.h
pkg-alists.o : i-svalue_cmp.h xalloc.h svalue.h simulate.h mstrings.h \
main.h interpret.h array.h my-alloca.h pkg-alists.h typedefs.h driver.h \
closure.h strfuns.h sent.h bytecode.h hash.h backend.h port.h config.h \
hosts/unix.h hosts/be/be.h machine.h
pkg-idna.o : ../mudlib/sys/idn.h xalloc.h simulate.h mstrings.h interpret.h \
typedefs.h pkg-idna.h driver.h svalue.h strfuns.h sent.h bytecode.h \
hash.h backend.h port.h config.h main.h hosts/unix.h hosts/be/be.h \
machine.h
pkg-mccp.o : ../mudlib/sys/telnet.h xalloc.h svalue.h object.h mstrings.h \
comm.h array.h pkg-mccp.h typedefs.h driver.h strfuns.h sent.h hash.h \
pkg-tls.h simulate.h port.h config.h bytecode.h hosts/unix.h \
hosts/be/be.h machine.h
pkg-mysql.o : xalloc.h svalue.h stdstrings.h simulate.h mstrings.h main.h \
instrs.h interpret.h array.h pkg-mysql.h my-alloca.h typedefs.h \
driver.h strfuns.h sent.h bytecode.h hash.h exec.h backend.h port.h \
config.h hosts/unix.h hosts/be/be.h machine.h
pkg-pcre.o : pcre/study.c pcre/maketables.c pcre/get.c pcre/pcre.c \
simulate.h interpret.h pkg-pcre.h driver.h pcre/internal.h \
pcre/chartables.c svalue.h strfuns.h sent.h bytecode.h typedefs.h \
backend.h pcre/pcre.h port.h config.h pcre/config.h main.h hosts/unix.h \
hosts/be/be.h machine.h
pkg-pgsql.o : ../mudlib/sys/pgsql.h xalloc.h stdstrings.h simulate.h \
mstrings.h mapping.h main.h interpret.h instrs.h gcollect.h array.h \
actions.h pkg-pgsql.h my-alloca.h typedefs.h driver.h svalue.h \
strfuns.h sent.h bytecode.h hash.h backend.h exec.h port.h config.h \
hosts/unix.h hosts/be/be.h machine.h
pkg-sqlite.o : xalloc.h stdstrings.h object.h svalue.h simulate.h \
mstrings.h interpret.h array.h my-alloca.h typedefs.h driver.h \
strfuns.h sent.h bytecode.h hash.h backend.h port.h config.h main.h \
hosts/unix.h hosts/be/be.h machine.h
pkg-tls.o : ../mudlib/sys/tls.h xalloc.h svalue.h sha1.h object.h \
mstrings.h main.h interpret.h comm.h array.h actions.h pkg-tls.h \
machine.h driver.h strfuns.h typedefs.h my-stdint.h sent.h hash.h \
bytecode.h backend.h simulate.h port.h config.h hosts/unix.h \
hosts/be/be.h
port.o : hosts/crypt.c main.h backend.h my-rusage.h driver.h machine.h \
typedefs.h port.h config.h hosts/unix.h hosts/be/be.h
ptmalloc.o : ptmalloc/malloc.c machine.h config.h ptmalloc/hooks.c \
ptmalloc/arena.c ptmalloc/thread-m.h ptmalloc/malloc.h \
ptmalloc/config.h
ptrtable.o : simulate.h mempools.h ptrtable.h driver.h svalue.h strfuns.h \
sent.h bytecode.h typedefs.h port.h config.h hosts/unix.h hosts/be/be.h \
machine.h
random.o : random.h driver.h port.h config.h hosts/unix.h hosts/be/be.h \
machine.h
regexp.o : main.h xalloc.h simulate.h interpret.h regexp.h driver.h \
typedefs.h svalue.h strfuns.h sent.h bytecode.h backend.h pkg-pcre.h \
port.h config.h pcre/pcre.h hosts/unix.h hosts/be/be.h machine.h
sha1.o : sha1.h my-stdint.h driver.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
simul_efun.o : xalloc.h swap.h svalue.h stdstrings.h simulate.h prolang.h \
ptrtable.h object.h mstrings.h lex.h interpret.h gcollect.h exec.h \
array.h simul_efun.h my-alloca.h typedefs.h driver.h strfuns.h sent.h \
bytecode.h hash.h backend.h port.h config.h main.h hosts/unix.h \
hosts/be/be.h machine.h
simulate.o : ../mudlib/sys/rtlimits.h ../mudlib/sys/regexp.h \
../mudlib/sys/files.h ../mudlib/sys/driver_hook.h \
../mudlib/sys/debug_info.h xalloc.h wiz_list.h svalue.h swap.h \
structs.h strfuns.h stdstrings.h simul_efun.h sent.h prolang.h \
pkg-sqlite.h pkg-tls.h otable.h object.h mstrings.h mregex.h mempools.h \
mapping.h main.h lex.h interpret.h heartbeat.h gcollect.h filestat.h \
ed.h comm.h closure.h call_out.h backend.h array.h actions.h simulate.h \
my-alloca.h typedefs.h driver.h hash.h exec.h ptrtable.h bytecode.h \
port.h config.h hosts/unix.h hosts/be/be.h machine.h
sprintf.o : xalloc.h swap.h svalue.h structs.h stdstrings.h simul_efun.h \
simulate.h sent.h random.h ptrtable.h object.h mstrings.h mapping.h \
main.h interpret.h comm.h closure.h array.h actions.h sprintf.h \
my-alloca.h typedefs.h driver.h strfuns.h hash.h exec.h bytecode.h \
backend.h pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h \
machine.h
stdstrings.o : mstrings.h stdstrings.h typedefs.h driver.h hash.h port.h \
config.h hosts/unix.h hosts/be/be.h machine.h
strfuns.o : xalloc.h svalue.h stdstrings.h simulate.h object.h mstrings.h \
mapping.h main.h interpret.h comm.h strfuns.h my-alloca.h typedefs.h \
driver.h sent.h bytecode.h hash.h backend.h pkg-tls.h port.h config.h \
hosts/unix.h hosts/be/be.h machine.h
structs.o : ../mudlib/sys/struct_info.h ../mudlib/sys/debug_info.h xalloc.h \
wiz_list.h stdstrings.h simulate.h object.h mstrings.h mapping.h main.h \
interpret.h gcollect.h exec.h array.h structs.h driver.h \
../mudlib/sys/lpctypes.h svalue.h strfuns.h typedefs.h sent.h \
bytecode.h hash.h backend.h port.h config.h hosts/unix.h hosts/be/be.h \
machine.h
swap.o : ../mudlib/sys/debug_info.h xalloc.h wiz_list.h svalue.h structs.h \
strfuns.h stdstrings.h simul_efun.h simulate.h random.h prolang.h \
otable.h object.h mstrings.h mempools.h mapping.h main.h interpret.h \
gcollect.h comm.h closure.h backend.h array.h swap.h typedefs.h \
driver.h hash.h exec.h ptrtable.h sent.h bytecode.h pkg-tls.h port.h \
config.h hosts/unix.h hosts/be/be.h machine.h
wiz_list.o : xalloc.h svalue.h stdstrings.h simulate.h object.h mstrings.h \
mapping.h main.h interpret.h gcollect.h backend.h array.h \
../mudlib/sys/wizlist.h wiz_list.h my-alloca.h typedefs.h driver.h \
strfuns.h sent.h bytecode.h hash.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
xalloc.o : xptmalloc.c sysmalloc.c slaballoc.c smalloc.c mstrings.h \
object.h exec.h simulate.h interpret.h gcollect.h backend.h xalloc.h \
driver.h ../mudlib/sys/debug_info.h ptmalloc/malloc.h svalue.h \
stdstrings.h sysmalloc.h array.h slaballoc.h typedefs.h smalloc.h \
hash.h sent.h bytecode.h strfuns.h main.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
# --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS PRECEDE ---
# --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS FOLLOW ---
actions.o : stdstrings.h
array.o : stdstrings.h
backend.o : stdstrings.h
call_out.o : stdstrings.h
closure.o : stdstrings.h instrs.h
comm.o : stdstrings.h
dumpstat.o : stdstrings.h instrs.h
ed.o : stdstrings.h
efuns.o : stdstrings.h
files.o : stdstrings.h
gcollect.o : stdstrings.h instrs.h
interpret.o : stdstrings.h instrs.h
lex.o : efun_defs.c stdstrings.h lang.h instrs.h
main.o : stdstrings.h
mkfunc.o : make_func.c
mstrings.o : stdstrings.h
object.o : stdstrings.h instrs.h
parse.o : stdstrings.h
parser.o : lang.c stdstrings.h instrs.h
pkg-mysql.o : stdstrings.h instrs.h
pkg-pgsql.o : stdstrings.h instrs.h
pkg-sqlite.o : stdstrings.h
simul_efun.o : stdstrings.h
simulate.o : stdstrings.h
sprintf.o : stdstrings.h
stdstrings.o : stdstrings.h
strfuns.o : stdstrings.h
structs.o : stdstrings.h
swap.o : stdstrings.h
wiz_list.o : stdstrings.h
xalloc.o : stdstrings.h
# --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS PRECEDE ---

491
src/access_check.c Normal file
View File

@ -0,0 +1,491 @@
/*---------------------------------------------------------------------------
* IP/time based access control.
*
* Copyright (C) 1995 by Joern Rennecke.
*---------------------------------------------------------------------------
* Access to the game is based on the user's IP address and the current time.
* These are matched against a set of rules and if a match is detected, a
* proper message is sent back and the connection is shutdown.
*
* This facility is active only if ACCESS_CONTROL has been defined in config.h
* If ACCESS_LOG is defined in config.h, all checks and their results are
* logged by comm.c in the specified file.
*
* The rules are read from the file ACCESS_FILE (defined in config.h,
* typically "ACCESS.ALLOW") which resides in the mudlib. Every line specifies
* one rule and has to follow the syntax given below. Lines with a '#' as
* first character count as comments and are ignored, as are lines which
* do not conform to the rule syntax (but except for empty lines this should
* be relied upon).
*
* The syntax for a rule is (no leading whitespace allowed!):
*
* <ipnum>:[p<port>]:<class>:<max>:<start>:<end>:<text>
* <ipnum>:[p<port>]:<class>:<max>:h<hours>:w<days>:m=<text>
*
* where
* ipnum: <byte>.<byte>.<byte>.<byte>, with byte = * or number
* There is only loose error checking - specifying an illegal
* address will have interesting consequences, but would
* most likely cause no error to occur.
* port: the port number to which the connection is made. Omission
* means 'any port'.
* class: number
* max: the maximum number of users, a number. The value -1 allows
* an unlimited number of users.
* start: hour this rule starts to be valid (0..23).
* end: hour this rule ceases to be valid (0..23).
* Setting both start and end to 0 skips any time check.
* hours: hours this rule is valid.
* This form allows several entries, separated with a ','.
* Every entry can be a single hour (0..23), or a range in the
* form '<start>-<end>'
* Omitting the entry skips any time check.
* days: the days this rule is valid.
* The syntax is similar to <hours> except for the
* allowable values: the days Sunday..Saturday are given as
* the numbers 0..6.
* Omitting the entry skips any day check.
* text: string to send if the rule matches.
*
* A class is defined by the first rule using it's number. This
* definition specifies the allowable <max>imum of users and the <text>
* to send. Subsequent rules for the same class just add new ipnumber/
* time rules, but don't change <max> or <text>
*
* ORDER MATTERS. That means if you allow 129.*.*.*, you have to put
* any restrictions on 129.132.*.* BEFORE this rule.
*
* Addresses not matching any rule at all are not allowed. To get around
* this, add an appropriate 'allow-all' rule *.*.*.* at the very end.
*
* An example rulefile:
*
* # SPARC cluster has access denied. Class 1
* 129.132.122.*:1:0:0:0:LPMUD access denied for your cluster.
*
* # CALL-1A0 has access limited to some maximum, for now 5 logins. Class 2
* 129.132.106.*:2:5:8:20:Sorry, LPMUD is currently full.
*
* # CALL-1A0 at all other times, its a 10 limit.
* # Due to the rule order, this is effectively limited to times
* # outside 8-20.
* 129.132.106.*:3:10:0:0:Sorry, LPMUD is currently full.
*
* # No more than 5 users allowed from localhost while working hours :-)
* 127.0.0.1:42:5:h8-12,13-18:w1-5:m=Pick a better time.
*
* # Everybody else is welcome.
* *.*.*.*:0:-1:0:0:This message should never be printed.
*
* The rule file is (re)read whenever the gamedriver detects a change in its
* timestamp.
*
* TODO: Make ACCESS_CONTROL a runtime option, also, when the file is
* TODO:: missing on driver startup (and just then), allow every access.
* TODO:: Alternatively, this could be made an
* TODO:: efun "string|int access_control(file, [interactive])" to be used
* TODO:: from TODO:: master.c::connect().
* TODO:: Or a driver hook with the settings "file", ({ "file", "logfile" })
* TODO:: and #'function(ip-address, port).
*---------------------------------------------------------------------------
*/
#include "driver.h"
#if defined(ACCESS_CONTROL)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <time.h>
#include "access_check.h"
#include "comm.h"
#include "filestat.h"
#include "xalloc.h"
#undef DEBUG_ACCESS_CHECK /* define to activate debug output */
/*-------------------------------------------------------------------------*/
#define MAX_MESSAGE_LENGTH 256
/* IP address/time rules, kept in a linked list.
* Every structure describes one rule, with a reference to the
* corresponding class structure.
*/
static struct access_address {
uint32 addr, mask; /* The IP address and a mask for the interesting parts */
int32 port; /* The port number (positive), or -1 for 'any port' */
int32 hour_mask; /* Bitmask: at which times is this rule valid? */
int32 wday_mask; /* Bitmask: at which days is this rule valid? */
struct access_class *class; /* The corresponding class */
struct access_address *next;
} *all_access_addresses = NULL;
/* Class descriptions, kept in a linked list.
* The structure is allocated big enough to keep the full message, the
* 8 characters listed in the definition are just a placeholder.
*/
static struct access_class {
long id; /* Class ID */
mp_int max_usage, usage; /* Max and current number of users */
struct access_class *next;
char message[8]; /* Placeholder for the message text buffer */
} *all_access_classes = NULL;
static time_t last_read_time = 0;
/*-------------------------------------------------------------------------*/
static struct access_class *
find_access_class (struct sockaddr_in *full_addr, int port)
/* Find and return the class structure for the given IP <full_addr> at
* the current time. Return NULL if no rule covers the IP at this time.
*/
{
uint32 addr;
struct access_address *aap;
time_t seconds;
struct tm *tm_p;
#ifdef DEBUG_ACCESS_CHECK
fprintf(stderr, "find_class for '%s':%d\n"
, inet_ntoa(*(struct in_addr*)&full_addr->sin_addr)
, port);
#endif
#ifndef USE_IPV6
addr = full_addr->sin_addr.s_addr;
#else
addr = (uint32) full_addr->sin_addr.s_addr;
/* TODO: DANGER: The above cast might break under IPv6 */
#endif
tm_p = NULL;
for (aap = all_access_addresses; aap; aap = aap->next) {
#ifdef DEBUG_ACCESS_CHECK
fprintf(stderr, " '%s':%ld, %ld %ld\n",
inet_ntoa(*(struct in_addr*)&aap->addr),
aap->port,
(long)aap->class->max_usage, (long)aap->class->usage);
#endif
if (aap->port >= 0 && aap->port != port)
continue;
if ((aap->addr ^ addr) & aap->mask)
continue;
if (aap->wday_mask >= 0) {
if (!tm_p) {
time(&seconds);
tm_p = localtime(&seconds);
#ifdef DEBUG_ACCESS_CHECK
fprintf(stderr, " h:%d w:%d\n", tm_p->tm_hour, tm_p->tm_wday);
#endif
}
if ( !((1 << tm_p->tm_hour) & aap->hour_mask) )
continue;
if ( !((1 << tm_p->tm_wday) & aap->wday_mask) )
continue;
}
#ifdef DEBUG_ACCESS_CHECK
fprintf(stderr, " found\n");
#endif
return aap->class;
}
#ifdef DEBUG_ACCESS_CHECK
fprintf(stderr, " not found\n");
#endif
return NULL;
}
/*-------------------------------------------------------------------------*/
static void
add_access_entry (struct sockaddr_in *full_addr, int login_port, long *idp)
/* Find the class structure for <full_addr> and increments its count
* of users. The id of the class is put into *idp.
* If there is no class, *idp is not changed.
*
* This function is called after the ACCESS_FILE has been (re-)read
* to reinitialize the current class usage counts.
*/
{
struct access_class *acp;
acp = find_access_class(full_addr, login_port);
if (acp) {
acp->usage++;
*idp = acp->id;
}
}
/*-------------------------------------------------------------------------*/
static void
read_access_file (void)
/* Read and parse the ACCESS_FILE, (re)creating all the datastructures.
* After the file has been read, the usage counts will be updated by
* calling comm::refresh_access_data, passing add_access_entry() as
* callback.
*/
{
FILE *infp;
struct access_address *aap, *next_aap, **last;
struct access_class *acp, *next_acp;
char message[MAX_MESSAGE_LENGTH];
int i;
int32 addr, mask;
/* Free the old datastructures */
for (aap = all_access_addresses; aap; aap = next_aap) {
next_aap = aap->next;
pfree((char *)aap);
}
for (acp = all_access_classes; acp; acp = next_acp) {
next_acp = acp->next;
pfree((char *)acp);
}
all_access_classes = NULL;
infp = fopen(ACCESS_FILE, "r");
if (!infp)
perror("driver: Can't read access file '" ACCESS_FILE "'");
FCOUNT_READ(ACCESS_FILE);
last = &all_access_addresses;
/* *last will be set to NULL at the end, so no dangling pointer
* will exist.
*/
/* The parse loop; it will terminate on file end or an error.
* Every rule is parsed in four iterations: the first three read
* the first bytes of the IP address, the fourth and last one
* everything else.
* If an address not specified in exactly 4 bytes, you will get
* nonsense, but no error message.
*/
if (infp) for(addr = mask = 0;;) {
long max_usage, class_id, port;
int first_hour, last_hour, m;
/* Parse the next IP address byte, i.e. everything up to the
* next . or : .
*/
addr <<= 8;
mask <<= 8;
m = fscanf(infp, "%9[^.:\n]%[.:]", message, message+12);
if (m != 2 || *message == '#')
{
do {
i = fgetc(infp);
if (i == EOF)
goto file_end;
} while(i != '\n');
addr = mask = 0;
continue;
}
if (*message != '*') {
int j;
j = atoi(message);
if ((unsigned int)j > 0xff)
break;
addr += j;
mask += 0xff;
}
if (message[12] == '.') /* Then another byte follows */
continue;
/* The ip-number may be followed with a port specification */
i = fscanf(infp, "p%ld:", &port);
if (!i)
port = -1;
/* Parse the time specs next. Start by trying the first (old)
* format.
*/
max_usage = 0;
message[0] = '\0';
i = fscanf(infp, "%ld:%ld:%d:%d:",
&class_id, &max_usage, &first_hour, &last_hour);
if (!i)
break;
aap = pxalloc(sizeof *aap);
if (!aap)
break;
*last = aap;
aap->addr = htonl(addr);
aap->mask = htonl(mask);
aap->port = port;
aap->wday_mask = -1; /* Default: valid on every day */
if (i == 4) { /* Old format */
if (first_hour || last_hour) {
aap->wday_mask = 0x7f;
if (first_hour <= last_hour) {
aap->hour_mask = (2 << last_hour) - (1 << first_hour);
} else {
aap->hour_mask = -(1 << first_hour) + (2 << last_hour) - 1;
}
}
} else if (i == 2) { /* New format */
char c, c2[2];
int32 *maskp;
for (;;) {
c = 'm';
fscanf(infp, "%c %1[=]", &c, c2);
switch(c)
{
case 'w':
maskp = &aap->wday_mask;
goto get_mask;
case 'h':
maskp = &aap->hour_mask;
get_mask:
mask = 0;
do {
int j, k;
*c2 = '\0';
if (!fscanf(infp, "%d %1[-,:] ", &j, c2))
break;
if (*c2 == '-') {
k = 24;
fscanf(infp, "%d %1[,:] ", &k, c2);
if (j <= k) {
mask |= (2 << k) - (1 << j);
} else {
mask |= -(1 << j) + (2 << k) - 1;
}
} else {
mask |= 1 << j;
}
} while (*c2 == ',');
*maskp = mask;
aap->wday_mask &= 0x7f; /* make sure it's not negative */
continue;
default:
ungetc(c, infp);
/* FALLTHROUGH */
case 'm':
break;
} /* switch */
break;
} /* for */
} /* if (i) */
/* The rest of the line is the message to print.
*/
fgets(message, (int)sizeof(message)-1, infp);
message[sizeof(message) - 1] = '\0';
/* Check if this rule creates a new class. If yes, allocate
* a new structure and assign message text and usage to it.
*/
for (acp = all_access_classes; acp; acp = acp->next) {
if (acp->id == class_id)
break;
}
if (!acp) {
size_t len;
len = strlen(message);
if (len && message[len-1] == '\n')
message[--len] = '\0';
acp = pxalloc(sizeof *acp - sizeof acp->message + 1 + len);
if (!acp) {
pfree((char *)aap);
break;
}
acp->id = class_id;
acp->max_usage = max_usage == -1 ? (mp_int)MAXINT : max_usage;
acp->usage = 0;
strcpy(acp->message, message);
acp->next = all_access_classes;
all_access_classes = acp;
}
/* Finishing touches. */
aap->class = acp;
last = &aap->next;
addr = mask = 0;
}
file_end: /* emergency exit from the loop */
/* Terminate the address list properly, then refresh the data */
*last = NULL;
refresh_access_data(add_access_entry);
}
/*-------------------------------------------------------------------------*/
char *
allow_host_access (struct sockaddr_in *full_addr, int login_port, long *idp)
/* Check if the IP address <full_addr> is allowed access at the current
* time. Return NULL if access is granted, else an error message.
*
* If access is allowed, *idp is set to the corresponding class id; this
* information is used later to re-initialize the class structures after
* a re-read of the ACCESS_FILE.
*
* The ACCESS_FILE is read by this function if it has been changed.
*/
{
struct stat statbuf;
struct access_class *acp;
if (ixstat(ACCESS_FILE, &statbuf))
perror("driver: Can't stat access file '" ACCESS_FILE "'");
else if (statbuf.st_mtime > last_read_time) {
last_read_time = statbuf.st_mtime;
read_access_file();
}
acp = find_access_class(full_addr, login_port);
if (acp) {
if (acp->usage >= acp->max_usage)
return acp->message;
acp->usage++;
*idp = acp->id;
return NULL;
}
return "No matching entry";
}
/*-------------------------------------------------------------------------*/
void
release_host_access (long num)
/* One user from the class <num> logged out, update the class structure
* accordingly.
*/
{
struct access_class *acp;
#ifdef DEBUG_ACCESS_CHECK
fprintf(stderr, "release_host_access %ld called.\n", num);
#endif
for (acp = all_access_classes; acp; acp = acp->next) {
if (acp->id != num)
continue;
acp->usage--;
break;
}
}
#endif /* ACCESS_CONTROL */
/***************************************************************************/

17
src/access_check.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef ACCESS_CHECK_H__
#define ACCESS_CHECK_H__ 1
#include "config.h"
#if defined(ACCESS_CONTROL)
#include "driver.h"
#include "comm.h"
extern char * allow_host_access(struct sockaddr_in *full_addr, int, long *idp);
extern void release_host_access(long num);
#endif /* ACCESS_CONTROL */
#endif /* ACCESS_CHECK_H__ */

2787
src/actions.c Normal file

File diff suppressed because it is too large Load Diff

42
src/actions.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef ACTIONS_H__
#define ACTIONS_H__ 1
#include "driver.h"
#include "typedefs.h" /* object_t */
/* --- Variables --- */
extern object_t *command_giver;
extern p_int alloc_action_sent;
/* --- Prototypes --- */
extern void free_action_temporaries(void);
extern void free_action_sent(action_t *p);
extern void remove_action_sent(object_t *ob, object_t *player);
extern void remove_shadow_action_sent(object_t *ob, object_t *player);
extern void remove_environment_sent(object_t *player);
extern void remove_shadow_actions (object_t *shadow, object_t *target);
extern void restore_command_context (rt_context_t *context);
extern Bool execute_command (char *str, object_t *ob);
extern svalue_t *v_add_action(svalue_t *sp, int num_arg);
extern svalue_t *v_command(svalue_t *sp, int num_arg);
extern svalue_t *f_disable_commands(svalue_t *sp);
extern svalue_t *f_enable_commands(svalue_t *sp);
extern svalue_t *f_execute_command(svalue_t *sp);
extern svalue_t *f_living(svalue_t *sp);
extern svalue_t *f_notify_fail(svalue_t *sp);
extern svalue_t *f_query_notify_fail(svalue_t *sp);
extern svalue_t *f_query_actions(svalue_t *sp);
extern svalue_t *f_query_verb(svalue_t *sp);
extern svalue_t *f_query_command(svalue_t *sp);
extern svalue_t *f_command_stack_depth(svalue_t *sp);
extern svalue_t *f_command_stack(svalue_t *sp);
extern svalue_t *f_set_modify_command(svalue_t *sp);
extern svalue_t *f_set_this_player(svalue_t *sp);
extern svalue_t *f_remove_action(svalue_t *sp);
extern svalue_t *f_match_command(svalue_t * sp);
#endif /* ACTIONS_H__ */

219
src/alloca.c Normal file
View File

@ -0,0 +1,219 @@
/*---------------------------------------------------------------------------
* Gamedriver alloca -- a portable alloca() implementation
* Based on the public-domain version by D.A. Gwyn.
*
*---------------------------------------------------------------------------
* This implementation of the PWB library alloca() function,
* which is used to allocate space off the run-time stack so
* that it is automatically reclaimed upon procedure exit,
* was inspired by discussions with J. Q. Johnson of Cornell
* and later extended by Lars Duening.
*
* It should work under any C implementation that uses an
* actual procedure stack (as opposed to a linked list of
* frames). There are some preprocessor constants that can
* be defined when compiling for your specific system, for
* improved efficiency; however, the defaults should be okay.
*
* The general concept of this implementation is to keep
* track of all alloca()-allocated blocks, and reclaim any
* that are found to be deeper in the stack than the current
* invocation. This heuristic does not reclaim storage as
* soon as it becomes invalid, but it will do so eventually.
*
* As a special case, alloca(0) reclaims storage without
* allocating any, including storage 'cached' by the implementation
* for fast reuse. It is a good idea to use alloca(0) in
* your main control loop, etc. to force garbage collection.
*
* As opposed to the original implementaion using malloc()/free(),
* this version utilizes the 'mempools' module to allocate the memory.
*---------------------------------------------------------------------------
*/
#include <stdlib.h>
#include <stdio.h>
#include "mempools.h"
typedef void *pointer; /* generic pointer type */
/*-------------------------------------------------------------------------*/
/* Define STACK_DIRECTION if you know the direction of stack
* growth for your system; otherwise it will be automatically
* deduced at run-time.
*
* STACK_DIRECTION > 0 => grows toward higher addresses
* STACK_DIRECTION < 0 => grows toward lower addresses
* STACK_DIRECTION = 0 => direction of growth unknown
*/
#if defined(AMIGA)
# define STACK_DIRECTION -1
#endif
#ifndef STACK_DIRECTION
# define STACK_DIRECTION 0 /* direction unknown */
#endif
#if STACK_DIRECTION != 0
# define STACK_DIR STACK_DIRECTION /* known at compile-time */
#else /* STACK_DIRECTION == 0; need run-time code */
static int stack_dir; /* 1 or -1 once known */
# define STACK_DIR stack_dir
#endif /* STACK_DIRECTION == 0 */
/*-------------------------------------------------------------------------*/
/* An "alloca header" is used to:
* (a) chain together all alloca()ed blocks;
* (b) keep track of stack depth.
*/
typedef struct hdr
{
struct hdr * next; /* for chaining headers */
char * deep; /* for stack depth measure */
mempool_t * pool; /* the memory pool */
} header;
static header *last_alloca_header = NULL; /* -> last alloca header */
static header *free_header = NULL; /* List of unused structures */
/*-------------------------------------------------------------------------*/
#if STACK_DIRECTION == 0
static void
find_stack_direction (void)
/* Find the direction of the stackgrowth and store the result (+1 or -1)
* into the global stack_dir.
*/
{
static char *addr = NULL; /* address of first `dummy', once known */
char dummy; /* to get stack address */
if (addr == NULL) /* initial call */
{
addr = &dummy;
find_stack_direction (); /* recurse once */
}
else /* second entry */
if (&dummy > addr)
stack_dir = 1; /* stack grew upward */
else
stack_dir = -1; /* stack grew downward */
}
#endif /* STACK_DIRECTION == 0 */
/*-------------------------------------------------------------------------*/
pointer
palloca (size_t size)
/* Allocate at least <size> bytes of memory "on the stack" and return a
* pointer to the start of the memory block. Return NULL if running out
* of memory.
*
* Allocating "on the stack" means that every allocation is associated with
* the call depth of the allocator. Allocations of a higher call depth
* cause the deallocation of any memory allocated on deepter call depths.
*
* Originally this memory was meant to be taken from the stack frame of
* the caller, but some systems and C implementations do not allow this.
*
* An allocation of 0 bytes is a special case, causing the deallocation of
* every memory block allocated so far.
*/
{
char probe; /* probes stack depth: */
register char * depth = &probe;
register header * hp; /* current header structure */
#if STACK_DIRECTION == 0
if (STACK_DIR == 0) /* (yet)unknown growth direction */
find_stack_direction ();
#endif
/* Reclaim garbage, defined as all alloca()ed storage that
* was allocated from deeper in the stack than currently.
*/
for (hp = last_alloca_header; hp != NULL;)
{
if ((STACK_DIR > 0 && hp->deep > depth)
|| (STACK_DIR < 0 && hp->deep < depth))
{
register header *np = hp->next;
mempool_reset(hp->pool); /* collect garbage */
hp->next = free_header;
free_header = hp;
hp = np; /* -> next header */
}
else
break; /* rest are not deeper */
}
last_alloca_header = hp; /* -> last valid storage */
/* From here on, hp is always == last_alloca_header; the
* use of the local however is a hint for the optimizer.
*/
if (size == 0)
{
while (free_header != NULL)
{
header * this = free_header;
free_header = free_header->next;
if (this->pool)
{
mempool_delete(this->pool);
}
free(this);
}
return NULL; /* no allocation required */
}
/* Allocate a new header structure if there is non for
* this particular stack depth. The new structure will
* be the new bottom of the header list.
*/
if (hp == NULL || hp->deep != depth)
{
if (free_header == NULL)
{
hp = malloc (sizeof (*hp));
if (!hp) { fprintf(stderr, "alloca: failed!\n"); return NULL; }
hp->pool = new_mempool(size_mempool(1));
if (!hp->pool)
{
free(hp);
fprintf(stderr, "alloca: failed!\n");
return NULL;
}
}
else
{
hp = free_header;
free_header = hp->next;
}
hp->next = last_alloca_header;
hp->deep = depth;
last_alloca_header = hp;
}
/* The actual allocation is easy: */
return mempool_alloc(hp->pool, size);
}
/***************************************************************************/

3209
src/array.c Normal file

File diff suppressed because it is too large Load Diff

137
src/array.h Normal file
View File

@ -0,0 +1,137 @@
#ifndef ARRAY_H__
#define ARRAY_H__ 1
#include "driver.h"
#include <stddef.h>
#include "typedefs.h"
#include "svalue.h"
/* --- Macros --- */
/* vector_t *ref_array(vector_t *a)
* Add another ref to array <a> and return the vector <a>.
*/
#define ref_array(a) ((a)->ref++, (a))
/* void free_array(vector_t *a)
* Subtract one ref from array <a>, and free the array fully if
* the refcount reaches zero.
*/
#define free_array(a) MACRO( if (--((a)->ref) <= 0) _free_vector(a); )
/* p_int deref_array(vector_t *a)
* Subtract one ref from array <a>, but don't check if it needs to
* be freed. Result is the number of refs left.
*/
#define deref_array(a) (--(a)->ref)
/* See array.c for a description of what the following macros do. */
/* Helper for LOCAL_VECn() */
#ifdef DEBUG
# define VEC_DEBUGREF(ref) ref,
#else
# define VEC_DEBUGREF(ref)
#endif
#include "svalue.h"
#define VEC_HEAD(size) size, 1, VEC_DEBUGREF(1) NULL
#define VEC_SIZE(v) ((v)->size)
#define LOCAL_VEC1(name, type1) \
struct { vector_t v; } name \
= { { VEC_HEAD(1), { { type1, { 0 } } } } }
#define LOCAL_VEC2(name, type1, type2) \
struct { vector_t v; svalue_t item[1]; } name \
= { { VEC_HEAD(2), { { type1, { 0 } } } }, { { type2, { 0 } } } }
/* --- Types --- */
/* --- struct vector: the array datatype ---
*
* When smalloc is used, the number of elements can be deduced from
* the memory block size, so the .size entry is not needed.
*/
struct vector_s {
p_int size; /* Number of contained elements */
p_int ref; /* Number of references */
#ifdef DEBUG
p_int extra_ref; /* Second refcount, used to check .ref. */
#endif
wiz_list_t *user; /* Save who made the vector */
svalue_t item[1];
};
/* --- Variables --- */
extern vector_t null_vector;
extern int num_arrays;
extern void (*allocate_array_error_handler) (const char *, ...);
/* --- Prototypes --- */
#if defined(MALLOC_TRACE)
#define allocate_array(n) (_allocate_array(n, __FILE__ "::allocate_array", __LINE__))
#define allocate_array_unlimited(n) (_allocate_array_unlimited(n, __FILE__ "::allocate_array", __LINE__))
#define allocate_uninit_array(n) (_allocate_array(n, __FILE__ "::allocate_uninit_array", __LINE__))
#define implode_string(a,d) (arr_implode_string(a,d, __FILE__ "::implode_string", __LINE__))
#else
#define allocate_array(n) _allocate_array(n)
#define allocate_array_unlimited(n) _allocate_array_unlimited(n)
#define allocate_uninit_array(n) _allocate_array(n)
#define implode_string(a,d) arr_implode_string(a,d)
#endif /* MALLOC_TRACE */
extern vector_t *_allocate_array(mp_int MTRACE_DECL);
extern vector_t *_allocate_array_unlimited(mp_int MTRACE_DECL);
extern vector_t *_allocate_uninit_array(mp_int MTRACE_DECL);
extern void _free_vector(vector_t *p);
extern void free_empty_vector(vector_t *p);
extern void check_for_destr(vector_t *v);
extern string_t *arr_implode_string(vector_t *, string_t * MTRACE_DECL);
extern vector_t *explode_string(string_t *str, string_t *del);
extern vector_t *slice_array(vector_t *p, mp_int from, mp_int to);
extern vector_t *add_array(vector_t *p, vector_t *q);
extern ptrdiff_t *get_array_order (vector_t * vec );
extern vector_t *order_array (vector_t *vec);
extern long lookup_key (svalue_t *key, vector_t *vec);
extern vector_t *subtract_array(vector_t *minuend, vector_t *subtrahend);
extern Bool is_ordered(vector_t *v);
extern vector_t *intersect_array(vector_t *vec1, vector_t *vec2);
extern vector_t *join_array(vector_t *vec1, vector_t *vec2);
extern vector_t * symmetric_diff_array (vector_t *vec1, vector_t *vec2);
extern svalue_t *v_allocate(svalue_t *sp, int num_arg);
extern svalue_t *x_filter_array(svalue_t *sp, int num_arg);
extern svalue_t *v_sort_array(svalue_t *sp, int num_arg);
extern svalue_t *x_map_array(svalue_t *sp, int num_arg);
extern svalue_t *f_transpose_array(svalue_t *sp);
extern svalue_t *v_filter_objects(svalue_t *sp, int num_arg);
extern svalue_t *v_map_objects(svalue_t *sp, int num_arg);
extern svalue_t *v_unique_array(svalue_t *sp, int num_arg);
extern void set_vector_user(vector_t *p, object_t *owner);
extern long total_array_size(void);
extern vector_t * shrink_array (vector_t *p, mp_int n);
#if defined(GC_SUPPORT)
extern void clear_array_size (void);
extern void count_array_size (vector_t *vec);
#endif
#endif /* ARRAY_H__ */

430
src/authlocal.c Executable file
View File

@ -0,0 +1,430 @@
/* authlocal.c 1.0.5 - auto-authenticate users connecting from localhost.
*
* The procedure you want to call from your code is getUID,
* which returns a uid_t, or 0 if authentication failed.
* ---->> Be sure to #define USE_AUTHLOCAL if you want it to work! <<----
*
* Remember that uid's under 100 won't be recognized; this is because
* they're normally system daemon accounts, not real users. If you
* need to change this behavior, change AUTHLOCAL_MIN_UID in authlocal.h
* before compiling.
*
* Copyright (C) 2002 Jeremy Monin <jeremy@shadowlands.org>
* http://shadowlands.org/authlocal/
* 1.0.5- 20020704.1140
* Fixed fencepost error re matching lines on buffer boundary.
* 1.0.4- 20020329.0140
* Added linux 2.4 support, many descriptive comments, efficiency
* improvements, and C-comments, not C++-comments (no //)
* original ver. was 19990907.1515
*/
#include <unistd.h> /* for ssize_t, uid_t */
#include <stdio.h>
#include <stdlib.h> /* for atol */
#include <sys/types.h> /* for open */
#include <sys/stat.h> /* for open */
#include <fcntl.h> /* for open */
#include <string.h> /* for memmove */
#include <sys/socket.h> /* this is */
#include <netinet/in.h> /* all for */
#include <arpa/inet.h> /* inet_addr */
#include "authlocal.h"
/* -- for debug --
#define DEBUG_AUTHLOCAL 1
#define USE_AUTHLOCAL 1
char* tcpstat_fname_str = "/proc/net/tcp";
#define TCPSTAT_FNAME tcpstat_fname_str
-- /for debug -- */
/*
* How it Works:
*
* When connecting to a TCP server from localhost, the server knows
* the arbitrary port# you're connecting from... under linux, the file
* /proc/net/tcp contains data about this socket, including its owner.
* This can be used to automatically, securely authenticate.
* See an example at the bottom of this file.
*
* It does lead to the problem of not _wanting_ to log in as yourself,
* but this is a separate issue. Also, be sure root doesn't log in this way.
* We also should check to be sure the logging-in user has a valid shell,
* but we don't right now.
*
* Tested and successful under linux 2.0.x, 2.2.x, 2.4.x
*
* Be sure to define USE_AUTHLOCAL if you want to use this;
* if this isn't defined, the entire getUID function will ALWAYS
* return 0 (failure). This means you don't need to change any of
* your other code, assuming you have a fallback method for authenticating
* people, which you'll need anyway if you want them to be able to
* get in from other hosts.
*/
/*
authlocal.c version 1.0.x - Automatic authentication of connections
from localhost.
Copyright (C) 2000-2002 Jeremy D. Monin (jeremy@shadowlands.org).
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef USE_AUTHLOCAL
/* yes, most of the file's in this ifdef. */
/* Only thing that isn't is, if USE_AUTHLOCAL
* isn't defined, the function that gets called
* from outside this module always returns 0 (failure),
* meaning you should fall back to standard username-and-pw-prompt
* authentication.
*/
/* format of /proc/net/tcp lines: (as of linux v2.0-2.4, unsure in other vers)
* We want to get the UID.
* sl addy addy st dunno:d d:dunno uh uid timeout inode ...
* \n n: local:port rem:port nn nnnn:nnn nn:nnnn nnn uid n n ...
* ^^^^^^^^ ^^^^^ in hex; each is 8:4 chars
* the ... after inode were added after 2.2.x.
*/
/* PATSIZE is used in allocating buffer space AND in moving the char ptr;
* it MUST be the correct length (incl trailing \0).
*/
#define PATSIZE (8+1+4+1+8+1+4+1) /* "0100007f:xxxx 0100007f:xxxx\0" */
#define LINEBUFSIZ 4096 /* must be much bigger than line len */
#ifndef TCPSTAT_FNAME
#define TCPSTAT_FNAME "/proc/net/tcp"
#endif
/* check to see if we need to read more chars into the buffer;
* if so, do that and adjust the end-of-buffer-data pointer.
* Either way, return it. Return NULL for EOF.
* On entry, *c points to the current buffer pos (the part we must keep).
* (We pass **c so we can change the current buffer pos pointer in the calling
* procedure.)
* *c must be past the start of the buffer. (*c != buf) Otherwise how can
* we have any room to read new data into?
*/
static char *read_chunk (char *buf, char **c, char *bufend, int inputfd)
{
ssize_t nread;
int inbufloc = *c - buf; /* how far into buffer are we? */
/* Must read some into the buffer, but retain partial lines (retain what's
* between *c and *bufend)... First, move current buffer contents up so we
* have room for more, discarding (overwriting) what's currently before *c
* in the buffer.
*/
if (inbufloc > 0)
{
memmove (buf, *c, LINEBUFSIZ - inbufloc);
*c = buf + (LINEBUFSIZ - inbufloc);
/* *c now points right after the end of the current content;
* but in some cases this will be null-terminated, so we need to
* not retain any \0's in the current content.
*/
--(*c);
while (( *c > buf ) && (**c == '\0'))
--(*c);
if (**c != '\0') ++(*c);
/* *c now points to where new stuff should be added; null-term it.
* we'll adjust *c again soon, but this is where we need it for now.
*/
**c = '\0';
}
/* so add the new stuff, try to fill to end of buffer */
nread = read (inputfd, *c, LINEBUFSIZ - (*c - buf) - 1);
if (nread == -1) {
#ifdef DEBUG_AUTHLOCAL
perror ("read");
#endif
return NULL;
}
if (nread == 0) /* EOF */
return NULL;
/* adjust c to start of buf, adjust end of buf ptr and return it */
nread += (*c - buf);
*(buf + nread) = '\0';
*c = buf;
return (buf + nread);
}
/** Begin reading from a file; return the end-of-buffer-data pointer,
* a pointer (inside buf) to the \0 right after the end of where we read,
* or return NULL if we can't read.
*/
static char *buf_begin_get(char *buf, int readfromfd)
{
ssize_t nread = read (readfromfd, buf, LINEBUFSIZ-1);
if (nread == -1) {
return NULL;
}
*(buf + nread) = '\0';
return (buf + nread);
}
/* returns 0 if something goes wrong and it can't be found.
* (UID 0 really shouldn't be logging in from a network anyway.)
*/
static uid_t getUID_impl (unsigned int /* type? */ localhost_ip,
int /* type? */ userportno, int daemonportno,
int inputfd)
{
char wantthis_in_hex[PATSIZE];
char buf[LINEBUFSIZ];
char *b;
char *bufend;
char *c;
sprintf (wantthis_in_hex, "%08X:%04X %08X:%04X",
localhost_ip, (int) userportno, localhost_ip, (int) daemonportno);
# ifdef DEBUG_AUTHLOCAL
//fprintf (stderr, "authlocal wantthis %s\n", wantthis_in_hex);
# endif
/* search for a line containing this */
bufend = buf_begin_get (buf, inputfd);
if (bufend == NULL) {
return (uid_t) 0; /* couldn't read */
}
/* we have c point at our current place in the buffer we search;
* as we read more, read_chunk will adjust c as the buffer moves.
*/
for ( c = buf;
(bufend != NULL) && (*c != '\0') && (c < bufend);
bufend = read_chunk (buf, &c, bufend, inputfd))
{
/* remember our place, in case c is about to become NULL */
b = c;
# ifdef DEBUG_AUTHLOCAL
// fprintf (stderr, "chunk is »%s«\n", b);
# endif
/* try to get c to point to the string we seek */
c = strstr (c, wantthis_in_hex);
if (c != NULL)
{
/* Found a match to our pattern.
* Now get uid and return it; we must skip ahead from where we
* found our src/dest port pair; to go from the end of our match
* to uid, we find and skip 5 blank areas (incl the one immediately
* after end of match).
* If we run out of string (find \0) before then, we have a match on
* a partial line and need to read more of the file into the buffer.
*/
int bkfld;
/* point c at end of pattern */
c += (PATSIZE - 1);
# ifdef DEBUG_AUTHLOCAL
fprintf (stderr, "authlocal found %s\n", wantthis_in_hex);
# endif
/* we're now at white space. We must skip 5 whitespace areas, and
* the 4 fields (non-whitespace) between them. Right after the 5th
* whitespace area is the uid field. We skip over that too, because
* we want to null-terminate that and then go back to its start.
*/
for (bkfld = 1; bkfld <= 5; ++bkfld)
{
/* inch c forward through whitespace */
while (*c <= ' ')
{
if (*c == '\0')
{
/* we're on a partial line, must read more file into
* the buffer and then retry the search.
*/
c = NULL;
break;
}
++c;
}
if (c == NULL) break;
/* now inch c forward through non-whitespace */
while (*c > ' ')
++c;
}
if (c != NULL)
{
/* we're now right after end of UID; null-terminate it and move back */
*c = '\0'; --c;
/* this is the field data; inch backward to next whitespace */
while (*c > ' ')
--c;
/* now nudge forward and read it! have a nice day,
* we're done.
*/
++c;
/* read it */
return (uid_t) atol(c); /* <-------- return the uid ------ */
} /* end if c-not-null (partial line after match) */
} /* end if c-not-null (no match at all) */
/* not found, grab more (to search through) from file into buffer, but
* we must retain the entire last line or two of the current buffer, in
* case we have just part of that line right now, and it's the right line
* but we don't know it because we don't have the entire line.
*/
c = bufend - 1;
/* find start of final line: */
while ((*c != '\n') && (c != buf))
--c;
if ((c == buf) && (*c != '\n'))
{
/* found no \n in the whole buffer; a very long line.
* the line must go away to make room. (not likely to happen)
*/
c = bufend;
} else {
char *lastlinec = c; /* remember start of final line */
/* find start of next-to-final line: */
while ((*c != '\n') && (c != buf))
--c;
if ((c == buf) && (*c != '\n'))
c = lastlinec; /* can't keep all of the 2 lines: keep 1 */
}
} /* end while-not-eof loop */
return (uid_t) 0; /* <-------- couldn't find it. ---------- */
}
#endif /* the big IFDEF */
/* Finally, here's what we need!
* Returns 0 if something goes wrong and it can't be found.
* (UID 0 really shouldn't be logging in from a network anyway.)
*/
uid_t getUID (unsigned int localhost_ip,
int userport, int daemonport)
{
#ifndef USE_AUTHLOCAL
# ifdef DEBUG_AUTHLOCAL
fprintf (stderr, "authlocal disabled\n");
# endif
return (uid_t) 0;
#else
uid_t retval;
int fd = open(TCPSTAT_FNAME, O_RDONLY);
if (fd == -1) {
#ifdef DEBUG_AUTHLOCAL
fprintf (stderr, "authlocal could not open " TCPSTAT_FNAME "\n");
#endif
return (uid_t) 0;
}
retval = getUID_impl (localhost_ip, userport, daemonport, fd);
# ifdef DEBUG_AUTHLOCAL
fprintf (stderr, "authlocal got uid %d for connection from %d on %d\n",
retval, userport, daemonport);
# endif
close (fd);
if (retval > AUTHLOCAL_MIN_UID)
return retval;
else
return 0;
#endif /* ifdef (USE_AUTHLOCAL) */
}
/* code for usage demonstration purposes. Note that it's commented out.
static struct in_addr localhost_ip;
localhost_ip.s_addr = htonl(0x7f000001);
...
struct sockaddr_in user_address;
int user_fd = accept
( server_fd, (sockaddr *)&user_address, &len );
...
uid_t authenticated = 0;
if (user_address.sin_addr.s_addr == localhost_ip.s_addr ) {
Auto-Authenticate user if logging in from localhost!
authenticated = getUID
( localhost_ip.s_addr, ntohs(user_address.sin_port),
server_portnum );
}
int main(int argc, char **argv)
{
int pnum_cli = 2048;
int pnum_srv = 5000;
int retuid;
if (argc > 1)
{
if (strncasecmp(argv[1], "0x", 2))
pnum_cli = (int) strtol(argv[1], (char **)NULL, 10);
else
pnum_cli = (int) strtol(argv[1], (char **)NULL, 16);
}
if (argc > 2)
{
if (strncasecmp(argv[2], "0x", 2))
pnum_srv = (int) strtol(argv[2], (char **)NULL, 10);
else
pnum_srv = (int) strtol(argv[2], (char **)NULL, 16);
}
#ifdef DEBUG_AUTHLOCAL
if (argc > 3)
tcpstat_fname_str = argv[3];
printf ("file for /proc/net/tcp is %s\n", tcpstat_fname_str);
#endif
printf ("lookin' for a connection from port %d (0x%04X) to %d (0x%04X)\n",
pnum_cli, pnum_cli, pnum_srv, pnum_srv);
retuid = (int) getUID ( inet_addr ("127.0.0.1"), pnum_cli, pnum_srv);
printf ("returned %d\n", retuid);
return (retuid ? 0 : 1);
}
authlocal.c ENDS. */

48
src/authlocal.h Executable file
View File

@ -0,0 +1,48 @@
/* authlocal.h - auto-authenticate users connecting from localhost.
The procedure you want to call from your code is getUID,
which returns a uid_t, or 0 if authentication failed.
Be sure to #define USE_AUTHLOCAL if you want it to work!
Copyright (C) 1999-2002 Jeremy D. Monin (jeremy@shadowlands.org).
http://shadowlands.org/authlocal/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _AUTHLOCAL_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Below this minimum UID, no users will be authenticated.
* (these are usually system pseudouser accounts.)
*/
#define AUTHLOCAL_MIN_UID 100
uid_t getUID (unsigned int localhost_ip,
int userport, int daemonport);
#ifdef __cplusplus
}
#endif
#define _AUTHLOCAL_H_
#endif

7
src/autoconf/Makefile Normal file
View File

@ -0,0 +1,7 @@
../configure: configure.in configure.head Makefile
autoconf
rm -f $@
cat configure.head configure >>$@
chmod +x $@
@rm configure

138
src/autoconf/acconfig.h Normal file
View File

@ -0,0 +1,138 @@
#ifndef MACHINE_H
#define MACHINE_H
@TOP@
/* Set in response to the signal handler return type, since not all
* compilers understand direct definition comparisons
*/
#undef RETSIGTYPE_VOID
/* does the compiler provide inline functions? */
#undef HAS_INLINE
/* Is the library function inet_ntoa() compatible with the compiler?
* TODO: Is there any platform where this is not the case?
*/
#undef INET_NTOA_OK
/* A mask that allows to extract an unsigned char from a signed */
#define CHARBIT_MASK 0xff
#undef RENAME_HANDLES_DIRECTORIES
/* Does the system have a getrusage call? */
#undef HAVE_GETRUSAGE
/* If so, is it restricted to user and system time? */
#undef GETRUSAGE_RESTRICTED
/* Is it available as a subfunction of syscall() ? */
#undef GETRUSAGE_VIA_SYSCALL
/* Can ru_utime / ru_stime be accessed as a timeval with tv_sec and tv_usec ? */
#undef RUSAGE_USEC
/* the atari strtol() used to consider characters '9' < c < 'A' to be numeric */
#undef STRTOL_BROKEN
/* does the libc consider it normal to free a null pointer? */
#undef FREE_NULL_POINTER
/* needs the first argument of strtol be declared as const ? */
#undef STRTOL_CONST_CHARP
/* Define if you have bcopy, and it handles overlapping ranges correctly. */
#undef OVERLAPPING_BCOPY
#define MALLOC_ALIGN 4
/* does the sys/types.h define the uint*_t types? */
#undef HAVE_INTTYPES
/* does the compiler know of a 'ssize_t' type? */
#undef HAVE_SSIZE_T
/* does the compiler know of a 'long long' type? */
#undef HAVE_LONG_LONG
/* does the compiler know of a 'bool' type? */
#undef HAVE_BOOL
/* what kind of pointer is used by malloc() et al */
#define POINTER *
#undef FREE_RETURNS_VOID
/* can we define our own malloc() safely? */
#undef SBRK_OK
/* The following is needed for smalloc without SBRK_OK to use memory
* efficiently. smalloc will malloc blocks that are a large power of
* two, minus EXTERN_MALLOC_OVERHEAD. If you have no idea what number to
* choose, compile & run util/overhead.c
*/
#define EXTERN_MALLOC_OVERHEAD 16
/* How to set a socket non-blocking */
#undef USE_IOCTL_FIONBIO
#undef USE_FCNTL_O_NDELAY
#undef USE_FCNTL_FNDELAY
/* Can F_SETOWN be used on a socket? */
#undef USE_FCNTL_SETOWN
/* Can SO_OOBINLINE be used on a socket? */
#undef USE_OOBINLINE
/* Does the machine offer IPv6? */
#undef HAS_IPV6
/* Does the machine offer iconv? */
#undef HAS_ICONV
/* Does the machine's iconv take a non-const 'char**' as first arg? */
#undef HAS_ICONV_NONCONST_IN
/* Does the machine offer PCRE? */
#undef HAS_PCRE
/* Does the machine offer IDNA? */
#undef HAS_IDN
/* Does the machine offer mySQL? */
#undef HAS_MYSQL
/* Does the machine offer PostgreSQL? */
#undef HAS_PGSQL
/* Does the machine offer SQLite3? */
#undef HAS_SQLITE3
/* Does SQLite3 use pthreads? */
#undef SQLITE3_USES_PTHREADS
/* Does the machine offer JSON (json-c)? */
#undef HAS_JSON
/* Does the machine offer expat? */
#undef HAS_EXPAT
/* Does the machine offer GnuTLS? */
#undef HAS_GNUTLS
#undef HAS_GNUTLS_VERSION
/* Does the machine offer OpenSSL/SSL? */
#undef HAS_OPENSSL
/* define the erq include file. */
#undef ERQ_INCLUDE
/* Does the machine offer pthreads? */
#undef HAS_PTHREADS
/* Does the machine offer pthread_atfork()? */
#undef HAS_PTHREAD_ATFORK
/* define the host-specific include file */
#undef HOST_INCLUDE
@BOTTOM@
#endif

View File

@ -0,0 +1,12 @@
#! /bin/sh
##
## never edit ./configure manually, it is being generated by autoconf.
##
## this special prefix prepended by autoconf/Makefile --lynX
if test "x$*" = "x"; then
echo "Restarting: configure --with-setting psyced"
settings/psyced
exit
fi

2894
src/autoconf/configure.in Normal file

File diff suppressed because it is too large Load Diff

1552
src/backend.c Normal file

File diff suppressed because it is too large Load Diff

63
src/backend.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef BACKEND_H__
#define BACKEND_H__ 1
#include "driver.h"
#include "typedefs.h"
#include "main.h" /* max_time */
/* --- Types --- */
/* struct statistic_s: Aggregate data for statistics.
*
* In particular the structures is used with update_statistic() in order
* to calculate a weighted average of the last period of time.
*/
struct statistic_s
{
mp_int last_time; /* Time of last weighted-average calculation. */
long sum; /* Sum since last weighted-average calculation. */
double weighted_avg; /* The current weighted average. */
};
/* --- Variables --- */
extern mp_int current_time;
extern Bool time_to_call_heart_beat;
extern volatile Bool comm_time_to_call_heart_beat;
extern uint32 total_player_commands;
extern volatile mp_int total_alarms;
extern uint num_listed_objs;
extern uint num_last_processed;
extern uint num_last_data_cleaned;
extern statistic_t stat_last_processed;
extern statistic_t stat_last_data_cleaned;
extern statistic_t stat_in_list;
extern Bool extra_jobs_to_do;
typedef enum { gcDont = 0, gcMalloc, gcEfun } GC_Request;
extern GC_Request gc_request;
extern statistic_t stat_load;
extern statistic_t stat_compile;
extern Bool mud_is_up;
/* --- Prototypes --- */
extern void clear_state (void);
extern void check_alarm (void);
extern void backend (void);
extern void preload_objects (int eflag);
extern svalue_t *f_debug_message (svalue_t *sp);
ALARM_HANDLER_PROT(catch_alarm);
extern void update_statistic (statistic_t * pStat, long number);
extern void update_statistic_avg (statistic_t * pStat, long number);
extern double relate_statistics (statistic_t sStat, statistic_t sRef);
extern void update_compile_av (int lines);
extern svalue_t *v_garbage_collection(svalue_t *sp, int num_arg);
extern svalue_t *f_query_load_average(svalue_t *sp);
/* --- Macros --- */
#endif /* BACKEND_H__ */

1073
src/bitstrings.c Normal file

File diff suppressed because it is too large Load Diff

24
src/bitstrings.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef BITSTRINGS_H__
#define BITSTRINGS_H__ 1
#include "driver.h"
#include "typedefs.h"
/* --- Variables --- */
/* --- Prototypes --- */
extern svalue_t *f_clear_bit (svalue_t *sp);
extern svalue_t *f_set_bit(svalue_t *);
extern svalue_t *f_test_bit(svalue_t *);
extern svalue_t *f_or_bits(svalue_t *);
extern svalue_t *f_and_bits(svalue_t *);
extern svalue_t *f_xor_bits(svalue_t *);
extern svalue_t *f_invert_bits(svalue_t *);
extern svalue_t *f_last_bit(svalue_t *);
extern svalue_t *f_next_bit(svalue_t *);
extern svalue_t *f_count_bits(svalue_t *);
extern svalue_t *v_copy_bits(svalue_t *, int num_arg);
#endif /* BITSTRINGS_H__ */

291
src/bytecode.h Normal file
View File

@ -0,0 +1,291 @@
#ifndef BYTECODE_H__
#define BYTECODE_H__ 1
/*---------------------------------------------------------------------------
* Types and Macros used to describe bytecode
*
*---------------------------------------------------------------------------
* While topically part of exec.h, the actual bytecode types and macros
* have been exported into this file to reduce the coupling on exec.h.
* Most files only need to know about bytecode_t and bytecode_p, and not
* about all the other stuff in exec.h .
*
* Bytecode
* --------
*
* As the name conveys, the LPC programs are compiled into a bytecode,
* assuming 8-Bit-Bytes. Since we have more than 256 opcodes, the less
* often used instructions are encoded in two-byte opcodes: a prefix
* byte and an sub-opcode. The translation opcode -> prefix:sub-opcode
* is defined in the instrs[] table using the .prefix and .opcode
* fields.
*
* To achieve platform independance, the driver does not operate directly
* with 'char's and 'char *'s, but instead with 'bytecode_t' and
* 'bytecode_p's. Combined with some macros this allows the implementation
* even on platforms with CHAR_BITs != 8.
* TODO: This support is far from complete/comprehensive, and some values
* TODO:: in the bytecode are stored in host-sizes and -layouts.
*
* The bytecode itself is divided into functions: the code for every
* function is (except for absolute jumps) selfcontained and prepended
* by a header holding the name of the function, and the number and types
* of expected arguments. The advantage is that for a given function
* the driver does not need to know if it is part of a program or a
* lambda closure compiled at runtime: in both cases all necessary
* information about the function is right where its code is.
*
* The maximum size of a program is limited by the biggest offset
* that can be stored in the 'functions' array, currently 1 MByte.
* A lot of internal offset counters are shorts even, though so far
* this never caused a problem.
*---------------------------------------------------------------------------
*/
#include "driver.h"
#include "typedefs.h"
/* --- Byte code ---
*
* The program code is stored as byte code. The following definitions
* and macros allow its implementation even on platforms with more than
* 8 bits per character.
* TODO: This portability is far from complete, and not used everywhere,
* TODO:: not even in the compiler.
*
* bytecode_t: an integral type holding the numbers 0..255.
* bytecode_p: an integral type addressing a bytecode. This need not
* be a pointer.
*
* bytecode_t GET_CODE(bytecode_p p)
* bytecode_t LOAD_CODE(bytecode_p p)
* Return the bytecode from *p, the LOAD_ variant then increments p.
*
* void PUT_CODE(bytecode_p p, bytecode_t c)
* void STORE_CODE(bytecode_p p, bytecode_t c)
* void RSTORE_CODE(bytecode_p p, bytecode_t c)
* Store the bytecode c in *p, the STORE_ variant then increments p.
* The RSTORE_ variant pre-decrements p.
*
* char GET_INT8(p) , LOAD_INT8(p)
* uchar GET_UINT8(p), LOAD_UINT8(p)
* Return the 8-Bit (unsigned) int stored at <p>, the LOAD_ variants
* then increment <p>.
*
* void PUT_INT8(p, char c), STORE_INT8(p, char c)
* void PUT_UINT8(p, uchar c), STORE_UINT8(p, uchar c)
* Store the 8-Bit (unsigned) int <c> into <p>, the STORE_ variants
* then increment <p>.
*
* void GET_SHORT ([unsigned] short d, bytecode_p p)
* void LOAD_SHORT([unsigned] short d, bytecode_p p)
* Load the (unsigned) short 'd' stored at <p>, the LOAD_ variant
* then increments <p>.
* TODO: Currently, all SHORTs must be 2 bytes.
*
* void PUT_SHORT (bytecode_p p, [unsigned] short d)
* void STORE_SHORT(bytecode_p p, [unsigned] short d)
* void RSTORE_SHORT(bytecode_p p, [unsigned] short d)
* Store the (unsigned) short <d> into <p>, the STORE_ variant
* then increments <p>. The RSTORE_ variant pre-decrements <p>.
* TODO: Currently, all SHORTs must be 2 bytes.
*
* void GET_INT16 ([unsigned] int16 d, bytecode_p p)
* void LOAD_INT16([unsigned] int16 d, bytecode_p p)
* Load the (unsigned) int16 'd' stored at <p>, the LOAD_ variant
* then increments <p>.
*
* void GET_LONG ([unsigned] long d, bytecode_p p)
* void LOAD_LONG([unsigned] long d, bytecode_p p)
* Load the (unsigned) long 'd' stored at <p>, the LOAD_ variant
* then increments <p>.
* TODO: Currently, all LONGs must be 4 bytes.
*
* void PUT_LONG (bytecode_p p, [unsigned] long d)
* void STORE_LONG(bytecode_p p, [unsigned] long d)
* void RSTORE_LONG(bytecode_p p, [unsigned] long d)
* Store the (unsigned) long <d> into <p>, the STORE_ variant
* then increments <p>. The RSTORE_ variant pre-decrements <p>.
* TODO: Currently, all LONGs must be 4 bytes.
*
* void LOAD_INT32([unsigned] int32 d, bytecode_p p)
* void GET_INT32([unsigned] int32 d, bytecode_p p)
* Load the (unsigned) in32 'd' stored at <p>, the LOAD_ variant
* then increments <p>.
*
* void STORE_INT32([unsigned] int32 d, bytecode_p p)
* void PUT_INT32([unsigned] int32 d, bytecode_p p)
* Store the (unsigned) int32 'd' at <p>, the STORE_ variant
* then increments <p>.
*/
#if CHAR_BIT == 8
typedef unsigned char bytecode_t;
typedef bytecode_t * bytecode_p;
#define GET_CODE(p) (*(p))
#define LOAD_CODE(p) (*(p)++)
#define PUT_CODE(p,c) (*(p) = (c))
#define STORE_CODE(p,c) (*(p)++ = (c))
#define RSTORE_CODE(p,c) (*--(p) = (c))
/* TODO: all these casts yield rvalues, so they shouldn't compile
* TODO:: (and on xlc on AIX some of them indeed don't).
*/
#define GET_UINT8(p) (*((unsigned char *)(p)))
#define GET_INT8(p) (*((signed char *)(p)))
#define LOAD_UINT8(p) (*((unsigned char *)(p)++))
#define LOAD_INT8(p) (*((signed char *)(p)++))
#define PUT_UINT8(p,c) (*((unsigned char *)(p)) = (c))
#define PUT_INT8(p,c) (*((signed char *)(p)) = (c))
#define STORE_UINT8(p,c) (*((unsigned char *)(p)++) = (c))
#define STORE_INT8(p,c) (*((signed char *)(p)++) = (c))
/* TODO: These generic mem-macros should go into a macros.h. See also
* TODO:: how mudos does it.
* Note: the lowlevel BYTE macros can't use MACRO(), since this is
* needed on the next abstraction level, and a macro can't be nested
* into itself.
*/
#define LOAD_2BYTE(d,p) ( ((char *)&(d))[0] = *(char *)(p)++, \
((char *)&(d))[1] = *(char *)(p)++)
#define GET_2BYTE(d,p) ( ((char *)&(d))[0] = ((char *)(p))[0], \
((char *)&(d))[1] = ((char *)(p))[1] )
#define STORE_2BYTE(p,d) do {\
unsigned char * _q, ** _qq; \
_q = (unsigned char *)(p); \
_qq = (unsigned char **)&(p); \
_q[0] = ((unsigned char *)&(d))[0]; \
_q[1] = ((unsigned char *)&(d))[1]; \
*_qq += 2; \
} while(0)
#define RSTORE_2BYTE(p,d) do {\
unsigned char * _q, ** _qq; \
_q = (unsigned char *)(p); \
_qq = (unsigned char **)&(p); \
_q[-2] = ((unsigned char *)&(d))[0]; \
_q[-1] = ((unsigned char *)&(d))[1]; \
*_qq -= 2; \
} while(0)
#define PUT_2BYTE(p,d) ( ((char *)(p))[0] = ((char *)&(d))[0], \
((char *)(p))[1] = ((char *)&(d))[1] )
#define LOAD_3BYTE(d,p) ( (d) = ((*(unsigned char *)(p)++) << 16) \
| ((*(unsigned char *)(p)++) << 8) \
| (*(unsigned char *)(p)++) )
#define GET_3BYTE(d,p) ( (d) = ((((unsigned char *)(p))[0]) << 16) \
| ((((unsigned char *)(p))[1]) << 8) \
| (((unsigned char *)(p))[2]) )
#define STORE_3BYTE(p,d) do {\
unsigned char * _q, ** _qq; \
unsigned long _d = (unsigned long)(d); \
_q = (unsigned char *)(p); \
_qq = (unsigned char **)&(p); \
_q[0] = (unsigned char) (_d >> 16) \
_q[1] = (unsigned char) (_d >> 8) \
_q[2] = (unsigned char) (_d) \
*_qq += 3; \
} while(0)
#define PUT_3BYTE(p,d) ( ((unsigned char *)(p))[0] = (unsigned char)((d) >> 16), \
((unsigned char *)(p))[1] = (unsigned char)((d) >> 8), \
((unsigned char *)(p))[2] = (unsigned char)(d) )
#define LOAD_4BYTE(d,p) ( ((char *)&(d))[0] = *(char *)(p)++, \
((char *)&(d))[1] = *(char *)(p)++, \
((char *)&(d))[2] = *(char *)(p)++, \
((char *)&(d))[3] = *(char *)(p)++ )
#define GET_4BYTE(d,p) ( ((char *)&(d))[0] = ((char *)(p))[0], \
((char *)&(d))[1] = ((char *)(p))[1], \
((char *)&(d))[2] = ((char *)(p))[2], \
((char *)&(d))[3] = ((char *)(p))[3] )
#define STORE_4BYTE(p,d) ( *(unsigned char *)(p)++ = ((char *)&(d))[0], \
*(unsigned char *)(p)++ = ((char *)&(d))[1], \
*(unsigned char *)(p)++ = ((char *)&(d))[2], \
*(unsigned char *)(p)++ = ((char *)&(d))[3] )
#define PUT_4BYTE(p,d) ( ((char *)(p))[0] = ((char *)&(d))[0], \
((char *)(p))[1] = ((char *)&(d))[1], \
((char *)(p))[2] = ((char *)&(d))[2], \
((char *)(p))[3] = ((char *)&(d))[3] )
#if SIZEOF_SHORT == 2
# define GET_SHORT(d,p) GET_2BYTE(d,p)
# define LOAD_SHORT(d,p) LOAD_2BYTE(d,p)
# define PUT_SHORT(p,d) MACRO(unsigned short _us = (unsigned short)d; \
PUT_2BYTE(p,_us);)
# define STORE_SHORT(p,d) MACRO(unsigned short _us = (unsigned short)d; \
STORE_2BYTE(p,_us);)
# define RSTORE_SHORT(p,d) MACRO(unsigned short _us = (unsigned short)d; \
RSTORE_2BYTE(p,_us);)
#else
# error "Unsupported size of short."
#endif
#if SIZEOF_LONG == 4
# define GET_LONG(d,p) GET_4BYTE(d,p)
# define LOAD_LONG(d,p) LOAD_4BYTE(d,p)
# define PUT_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
PUT_4BYTE(p,_us);)
# define STORE_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
STORE_4BYTE(p,_us);)
# define RSTORE_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
RSTORE_4BYTE(p,_us);)
#elif SIZEOF_LONG == 8 && SIZEOF_INT == 4
# define GET_LONG(d,p) MACRO(int _ui; GET_4BYTE(_ui,p); \
d = _ui;)
# define LOAD_LONG(d,p) MACRO(int _ui; LOAD_4BYTE(_ui,p); \
d = _ui;)
# define PUT_LONG(p,d) MACRO(unsigned int _ui = (unsigned int)d; \
PUT_4BYTE(p,_ui);)
# define STORE_LONG(p,d) MACRO(unsigned int _ui = (unsigned int)d; \
STORE_4BYTE(p,_ui);)
# define RSTORE_LONG(p,d) MACRO(unsigned int _ui = (unsigned int)d; \
RSTORE_4BYTE(p,_ui);)
#else
# error "Unsupported size of long."
#endif
#define LOAD_INT16(d,p) LOAD_2BYTE(d,p)
#define GET_INT32(d,p) GET_4BYTE(d,p)
#define PUT_INT32(p,d) PUT_4BYTE(p,d)
#ifdef NO64BIT
# define LOAD_INT32(d,p) LOAD_4BYTE(d,p)
# define STORE_INT32(p,d) STORE_4BYTE(p,d)
#else
# define GET_LONG(d,p) GET_4BYTE(d,p)
# define LOAD_LONG(d,p) LOAD_4BYTE(d,p)
# define PUT_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
PUT_4BYTE(p,_us);)
# define STORE_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
STORE_4BYTE(p,_us);)
# define RSTORE_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
RSTORE_4BYTE(p,_us);)
/* TODO: The above assumes sizeof(long) == 4. */
# define LOAD_INT32(d,p) LOAD_2BYTE(d,p)
#endif
#endif
#ifndef GET_CODE
# error "No bytecode type defined."
#endif
/***************************************************************************/
#endif /* BYTECODE_H__ */

847
src/call_out.c Normal file
View File

@ -0,0 +1,847 @@
/*---------------------------------------------------------------------------
* Gamedriver Callout handling.
*
*---------------------------------------------------------------------------
* Callouts are delayed calls to (non-static) functions, with delays
* measured in seconds. The minimal resolution is of course the duration
* a backend cycle. The command_giver is saved over the delay.
*
* As a simplistic measure against 'rabbits' (think fork-bombs using
* callouts), the callouts of one user can use only MAX_EVAL_COST at
* one time altogether.
*
* Pending call outs are held in a list, sorted in ascending order of
* remaining delaytime. The actual delay values stored are deltas: the
* delay this callout is to be scheduled after its predecessor in
* the list.
*
* TODO: It would be nice if the callout would store from where the
* TODO:: callout originated and fake a control-stack entry for a proper
* TODO:: traceback. However, this has to take swapping into account.
*---------------------------------------------------------------------------
*/
#include "driver.h"
#include "typedefs.h"
#include "call_out.h"
#include "actions.h"
#include "array.h"
#include "backend.h"
#include "closure.h"
#include "comm.h"
#include "exec.h"
#include "gcollect.h"
#include "interpret.h"
#include "main.h"
#include "mstrings.h"
#include "object.h"
#include "simulate.h"
#include "stdstrings.h"
#include "strfuns.h"
#include "svalue.h"
#ifdef USE_SWAP
#include "swap.h"
#endif
#include "wiz_list.h"
#include "xalloc.h"
#include "../mudlib/sys/debug_info.h"
/*-------------------------------------------------------------------------*/
/* The description of one callout.
*
* The function to call be either given by object:name or as closure.
*/
struct call {
struct call *next; /* link to next structure */
/* TODO: p_int or mp_int */ int delta; /* Delay in relation to the previous structure */
callback_t fun;
object_t *command_giver; /* the saved command_giver */
};
static struct call *call_list = NULL;
/* The list of pending call_outs, sorted in ascending order of delay.
*/
static long num_callouts = 0;
/* Number of active callouts.
*/
/*-------------------------------------------------------------------------*/
static INLINE void
free_call (struct call *cop)
/* Deallocate all resources bound to <cop> and put <cop> into the free list.
* This can be used for used and unused callouts alike.
*/
{
free_callback(&(cop->fun));
if (cop->command_giver)
free_object(cop->command_giver, "free_call");
pfree(cop);
} /* free_call() */
/*-------------------------------------------------------------------------*/
static void
insert_call (struct call *cop, int delay)
/* Inser the call_out structure <cop> with the <delay> into the callout
* list.
*/
{
struct call **copp; /* Auxiliary pointers for list insertion */
struct call *cop2;
num_callouts++;
for (copp = &call_list; NULL != (cop2 = *copp); copp = &cop2->next)
{
int delta;
if ((delta = cop2->delta) >= delay)
{
cop2->delta -= delay;
cop->delta = delay;
cop->next = *copp;
*copp = cop;
return;
}
delay -= (delta >= 0 ? delta : 0);
/* Especially when called from within a call_out, delta may be
* negative.
*/
}
*copp = cop;
cop->delta = delay;
cop->next = NULL;
} /* insert_call() */
/*-------------------------------------------------------------------------*/
svalue_t *
v_call_out (svalue_t *sp, int num_arg)
/* EFUN: call_out()
*
* void call_out(string fun, int delay, mixed arg, ...)
* void call_out(closure cl, int delay, mixed arg, ...)
*
* Set up a call to function fun or closure cl in the current
* object. The call will take place in delay seconds, with the
* remaining argument list provided. References in the argument list
* will be passed as number 0, though.
*/
{
svalue_t *arg; /* Pointer to efun arguments */
int delay;
struct call *cop; /* New callout structure */
int error_index;
arg = sp - num_arg + 1;
/* If the current object is destructed, free everything on the stack
* and return.
*/
if (current_object->flags & O_DESTRUCTED)
{
do {
free_svalue(sp--);
} while (--num_arg);
return sp;
}
if (max_callouts && max_callouts <= num_callouts)
{
errorf("Too many callouts at once (max. %ld).\n", (long)max_callouts);
/* NOTREACHED */
}
/* Get a new call structure.
* Note: it is not useful to pool these allocations, as muds tend
* to have spikes of high callout usage, but a low longterm average
* usage. Any overhead savings by a pool are more than made up
* by the unused structures sitting around.
*/
cop = pxalloc(sizeof (struct call));
/* Get the function designation from the stack */
if (arg[0].type == T_STRING)
{
error_index = setup_function_callback(&(cop->fun), current_object
, arg[0].u.str
, num_arg-2, arg+2
, MY_TRUE
);
free_string_svalue(arg);
}
else
error_index = setup_closure_callback(&(cop->fun), arg
, num_arg-2, arg+2
, MY_TRUE
);
if (error_index >= 0)
{
pfree(cop); /* The callback structure was invalidated automatically. */
vefun_bad_arg(error_index+2, arg-1);
/* NOTREACHED */
return arg-1;
}
/* We can do the callout.
*/
cop->command_giver = command_giver; /* save current player context */
if (command_giver)
ref_object(command_giver, "f_call_out"); /* Bump its ref */
/* Adjust the stack and get the delay */
sp = arg - 1;
delay = arg[1].u.number;
if (delay < 0)
delay = 0;
/* Insert the new structure at its proper place in the list */
insert_call(cop, delay);
return sp;
} /* v_call_out() */
/*-------------------------------------------------------------------------*/
void
call_out (void)
/* Check if there is any callout due to be called. If yes, do so.
* This function is called from the heart_beat handling in the backend.c.
* It sets up its own error recovery context so that errors during an
* execution won't disturb the rest of the game.
*/
{
static int last_time;
/* Last time this function was called */
static struct call *current_call_out;
/* Current callout, static so that longjmp() won't clobber it. */
static object_t *called_object;
/* Object last called, static so that longjmp() won't clobber it */
struct error_recovery_info error_recovery_info;
/* No calls pending: just update the last_time and return */
if (call_list == NULL)
{
last_time = current_time;
return;
}
/* If not set yet, initialize last_time on the first call */
if (last_time == 0)
last_time = current_time;
/* Update the first .delta in the list (so it won't happen
* twice in case of an error.
*/
call_list->delta -= current_time - last_time;
last_time = current_time;
current_interactive = NULL;
/* Activate the local error recovery context */
error_recovery_info.rt.last = rt_context;
error_recovery_info.rt.type = ERROR_RECOVERY_BACKEND;
rt_context = (rt_context_t *)&error_recovery_info;
if (setjmp(error_recovery_info.con.text))
{
/* An error occured: recover and delete the guilty callout */
struct call *cop;
object_t *ob;
wiz_list_t *user;
mark_end_evaluation();
clear_state();
debug_message("%s Error in call out.\n", time_stamp());
cop = current_call_out;
ob = called_object;
if (ob)
{
/* Disable the user for this call_out cycle. This is mainly
* meant to stop runaway call_outs causing too-long-evaluations.
*/
user = ob->user;
user->call_out_cost = -1;
}
free_call(cop);
}
/* (Re)initialize stack and tracing */
tracedepth = 0;
/* Loop over the call list until it is empty or until all
* due callouts are processed.
*/
while (call_list && call_list->delta <= 0)
{
object_t *ob;
struct call *cop;
wiz_list_t *user;
/* Move the first callout out of the chain.
*/
cop = call_list;
call_list = cop->next;
current_call_out = cop;
num_callouts--;
/* A special case:
* If a lot of time has passed, so that current call out was missed,
* then it will have a negative delta. This negative delta implies
* that the next call out in the list has to be adjusted.
*/
if (cop->delta < 0 && call_list)
call_list->delta += cop->delta;
/* Get the object for the function call and make sure it's valid */
ob = callback_object(&(cop->fun));
if (!ob)
{
/* Nothing to call */
free_call(cop);
continue;
}
#ifdef USE_SWAP
if (O_PROG_SWAPPED(ob)
&& load_ob_from_swap(ob) < 0)
{
debug_message("%s Error in call_out: out of memory: "
"unswap object '%s'.\n", time_stamp()
, get_txt(ob->name));
free_call(cop);
continue;
}
#endif
/* Check if the user has exceeded its eval limit for this cycle.
* If yes, reschedule the call_out for one second later.
*/
user = ob->user;
if (user->last_call_out == current_time
&& user->call_out_cost < 0
)
{
debug_message("%s call_out: user '%s' had an error: "
"rescheduling call_out.\n"
, time_stamp()
, user->name ? get_txt(user->name) : "<null>");
insert_call(cop, 1);
continue;
}
/* Determine the command_giver for the call.
* If a command_giver is given in the callout structure, use that one.
* Else test the object to be called or the object it's shadowing for
* being a command_giver.
* Remember that a now-destructed commandgiver is different from having
* no commandgiver to begin with.
*/
if (cop->command_giver)
{
if (!(cop->command_giver->flags & O_DESTRUCTED))
{
command_giver = cop->command_giver;
if (O_IS_INTERACTIVE(command_giver))
trace_level = O_GET_INTERACTIVE(command_giver)->trace_level;
}
else
command_giver = NULL;
}
#ifdef USE_SHADOWING
else if (ob->flags & O_SHADOW)
{
/* Look at the object which is at the end of the shadow chain.
*/
shadow_t *shadow_sent;
object_t *sob;
sob = ob;
while ((shadow_sent = O_GET_SHADOW(sob)), shadow_sent->shadowing)
sob = shadow_sent->shadowing;
if (sob->flags & O_ENABLE_COMMANDS)
{
command_giver = sob;
if (shadow_sent->ip)
trace_level = shadow_sent->ip->trace_level;
else
trace_level = 0;
}
else
{
command_giver = NULL;
trace_level = 0;
}
}
#endif
else
{
/* If at all, this object must be the command_giver */
if (ob->flags & O_ENABLE_COMMANDS)
command_giver = ob;
else
command_giver = NULL;
trace_level = 0;
}
/* Finally, call the function (unless the object was destructed).
*/
called_object = current_object = ob;
if (user->last_call_out != current_time)
{
user->last_call_out = current_time;
CLEAR_EVAL_COST;
}
else
assigned_eval_cost = eval_cost = user->call_out_cost;
mark_start_evaluation();
(void)backend_callback(&(cop->fun), 0);
user->call_out_cost = eval_cost;
mark_end_evaluation();
/* The function call used up all the arguments, now free
* the rest
*/
free_call(cop);
} /* while (callouts pending) */
rt_context = error_recovery_info.rt.last;
} /* call_out() */
/*-------------------------------------------------------------------------*/
static void
find_call_out (object_t *ob, svalue_t *fun, Bool do_free_call)
/* Find the (first) callout for <ob>/<fun> (or <fun> if it is a closure).
* If <do_free_call> is true, the found callout is removed.
*
* In either case, *<fun> is modified into a NUMBER holding the time left
* for the found/removed callout. If no callout was found, -1 is returned.
*/
{
struct call **copp, *cop;
int delay = 0;
string_t *fun_name;
/* Find callout by closure */
if (fun->type != T_STRING)
{
if (fun->type == T_CLOSURE)
{
for (copp = &call_list; NULL != (cop = *copp); copp = &cop->next)
{
delay += cop->delta;
if (cop->fun.is_lambda
&& closure_eq(&(cop->fun.function.lambda), fun)
)
{
goto found;
}
}
/* Not found */
free_svalue(fun);
put_number(fun, -1);
return;
found:
free_svalue(fun);
if (do_free_call)
{
if (cop->next)
cop->next->delta += cop->delta;
*copp = cop->next;
free_call(cop);
num_callouts--;
}
/* It is possible to have delay < 0 if we are
* called from inside call_out() .
*/
if (delay < 0)
delay = 0;
put_number(fun, delay);
return;
}
fatal("find_call_out() got %s, expected string/closure.\n"
, typename(fun->type));
/* NOTREACHED */
}
/* Find callout by object/name */
fun_name = find_tabled(fun->u.str);
if (fun_name != NULL)
for (copp = &call_list; NULL != (cop = *copp); copp = &cop->next)
{
delay += cop->delta;
if (cop->fun.function.named.ob == ob
&& cop->fun.function.named.name == fun_name
&& !cop->fun.is_lambda)
{
if (do_free_call)
{
if (cop->next)
cop->next->delta += cop->delta;
*copp = cop->next;
free_call(cop);
num_callouts--;
}
if (delay < 0)
delay = 0;
free_svalue(fun);
put_number(fun, delay);
return;
}
} /* if()for() */
/* Not found */
free_svalue(fun);
put_number(fun, -1);
} /* find_call_out() */
/*-------------------------------------------------------------------------*/
size_t
call_out_status (strbuf_t *sbuf, Bool verbose)
/* Compute and return the amount of memory used by callouts.
* If <verbose> is true, write detailed statistics to the current user.
*/
{
remove_stale_call_outs();
if (verbose)
{
strbuf_add(sbuf, "\nCall out information:\n");
strbuf_add(sbuf,"---------------------\n");
strbuf_addf(sbuf, "Number of call outs: %8ld, %8ld bytes\n",
num_callouts, num_callouts * sizeof (struct call));
}
else
{
strbuf_addf(sbuf, "call out:\t\t\t%8ld %9ld\n"
, num_callouts, num_callouts * sizeof (struct call));
}
return num_callouts * sizeof (struct call);
} /* call_out_status() */
/*-------------------------------------------------------------------------*/
void
callout_dinfo_status (svalue_t *svp, int value)
/* Return the callout information for debug_info(DINFO_DATA, DID_STATUS).
* <svp> points to the svalue block for the result, this function fills in
* the spots for the object table.
* If <value> is -1, <svp> points indeed to a value block; other it is
* the index of the desired value and <svp> points to a single svalue.
*/
{
#define ST_NUMBER(which,code) \
if (value == -1) svp[which].u.number = code; \
else if (value == which) svp->u.number = code
remove_stale_call_outs();
ST_NUMBER(DID_ST_CALLOUTS, num_callouts);
ST_NUMBER(DID_ST_CALLOUT_SIZE, num_callouts * sizeof(struct call));
#undef ST_NUMBER
} /* callout_dinfo_status() */
/*-------------------------------------------------------------------------*/
#ifdef USE_PARANOIA
void
count_extra_ref_from_call_outs (void)
/* Used to debug refcounts: count all refcounts in the callout handling.
*/
{
struct call *cop;
for (cop = call_list; cop; cop = cop->next)
{
count_callback_extra_refs(&(cop->fun));
if (cop->command_giver)
count_extra_ref_in_object(cop->command_giver);
}
}
#endif
/*-------------------------------------------------------------------------*/
void
remove_stale_call_outs (void)
/* GC and statistics support: Remove all callouts referencing destructed
* objects.
*/
{
struct call **copp, *cop;
for (copp = &call_list; NULL != (cop = *copp); )
{
object_t *ob;
ob = callback_object(&(cop->fun));
if (!ob)
{
num_callouts--;
if (cop->next)
cop->next->delta += cop->delta;
*copp = cop->next;
free_call(cop);
continue;
}
copp = &cop->next;
}
} /* remove_stale_call_outs() */
#ifdef GC_SUPPORT
/*-------------------------------------------------------------------------*/
void
clear_ref_from_call_outs (void)
/* GC Support: Clear all refs from the callout handling.
*/
{
struct call *cop;
for (cop = call_list; cop; cop = cop->next)
{
object_t *ob;
clear_ref_in_callback(&(cop->fun));
if (NULL != (ob = cop->command_giver))
clear_object_ref(ob);
}
} /* clear_ref_from_call_outs() */
/*-------------------------------------------------------------------------*/
void
count_ref_from_call_outs (void)
/* GC Support: Clear all refs from the callout handling.
*/
{
struct call *cop;
object_t *ob;
for (cop = call_list; cop; cop = cop->next)
{
count_ref_in_callback(&(cop->fun));
if ( NULL != (ob = cop->command_giver) )
{
if (ob->flags & O_DESTRUCTED) {
reference_destructed_object(ob);
cop->command_giver = NULL;
} else {
ob->ref++;
}
}
}
} /* count_ref_from_call_outs() */
#endif /* GC_SUPPORT */
/*-------------------------------------------------------------------------*/
static vector_t *
get_all_call_outs (void)
/* Construct an array of all pending call_outs (whose object is not
* destructed). Every item in the array is itself an array of 4 or
* more entries:
* 0: The object (only if the function is a string).
* 1: The function (string or closure).
* 2: The delay.
* 3..: The argument(s).
*/
{
int i, next_time;
struct call *cop;
vector_t *v;
/* Count the number of pending callouts and allocate
* the result array.
*/
for (i = 0, cop = call_list; cop; cop = cop->next)
{
if (!callback_object(&(cop->fun)))
continue;
i++;
}
v = allocate_array(i); /* assume that all elements are inited to 0 */
/* Create the result array contents.
*/
next_time = 0;
for (i=0, cop = call_list; cop; cop = cop->next)
{
vector_t *vv;
object_t *ob;
next_time += cop->delta;
ob = callback_object(&(cop->fun));
if (!ob)
continue;
/* Get the subarray */
vv = allocate_array(3 + cop->fun.num_arg);
if (cop->fun.is_lambda)
{
if (cop->fun.function.lambda.x.closure_type == CLOSURE_LFUN)
put_ref_object( vv->item
, cop->fun.function.lambda.u.lambda->function.lfun.ob
, "get_all_call_outs");
else
put_ref_object(vv->item, ob, "get_all_call_outs");
assign_svalue_no_free(&vv->item[1], &cop->fun.function.lambda);
}
else
{
put_ref_object(vv->item, ob, "get_all_call_outs");
put_ref_string(vv->item + 1, cop->fun.function.named.name);
}
vv->item[2].u.number = next_time;
if (cop->fun.num_arg > 0)
{
svalue_t *source, *dest;
int nargs;
nargs = cop->fun.num_arg;
if (nargs > 1)
source = cop->fun.arg.u.lvalue;
else
source = &(cop->fun.arg);
dest = &vv->item[3];
do {
assign_svalue_no_free(dest++, source++);
} while (--nargs);
}
put_array(v->item + i, vv);
i++;
}
return v;
} /* get_all_call_outs() */
/*-------------------------------------------------------------------------*/
svalue_t *
f_call_out_info (svalue_t *sp)
/* EFUN call_out_info()
*
* mixed *call_out_info(void)
*
* Get information about all pending call outs. The result is an
* array in which every entry is itself an array describing one
* call_out.
*
* The efun causes the the privilege violation ("call_out_info",
* this_object()). If it is not satisfied, the result will be
* the empty array.
*/
{
if (privilege_violation(STR_CALL_OUT_INFO, &const0, sp))
{
push_array(sp, get_all_call_outs());
}
else
{
push_ref_array(sp, &null_vector);
}
return sp;
} /* f_call_out_info() */
/*-------------------------------------------------------------------------*/
svalue_t *
f_find_call_out (svalue_t *sp)
/* EFUN find_call_out()
*
* int find_call_out(string func)
* int find_call_out(closure func)
*
* Find the first call-out due to be executed for function func
* in the current object, and return the time left. If no call-out
* is found return -1.
*/
{
find_call_out(current_object, sp, MY_FALSE);
return sp;
} /* f_find_call_out() */
/*-------------------------------------------------------------------------*/
svalue_t *
f_remove_call_out (svalue_t *sp)
/* EFUN remove_call_out()
*
* int remove_call_out(string fun)
* int remove_call_out(closure fun)
*
* Remove next pending call-out for function fun in this object.
* The time left is returned.
*
* -1 is returned if there were no call-outs pending to this
* function.
*/
{
find_call_out(current_object, sp, MY_TRUE);
return sp;
} /* f_remove_call_out() */
/***************************************************************************/

29
src/call_out.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef CALL_OUT_H__
#define CALL_OUT_H__ 1
#include "driver.h"
#include "typedefs.h"
#include "strfuns.h" /* strbuf_t */
/* --- Prototypes --- */
extern void call_out(void);
extern size_t call_out_status(strbuf_t *sbuf, Bool verbose);
extern void callout_dinfo_status(svalue_t *svp, int value);
extern void remove_stale_call_outs(void);
extern svalue_t *v_call_out(svalue_t *sp, int num_arg);
extern svalue_t *f_call_out_info(svalue_t *sp);
extern svalue_t *f_find_call_out(svalue_t *sp);
extern svalue_t *f_remove_call_out(svalue_t *sp);
#ifdef DEBUG
extern void count_extra_ref_from_call_outs(void);
#endif
#ifdef GC_SUPPORT
extern void clear_ref_from_call_outs(void);
extern void count_ref_from_call_outs(void);
#endif
#endif /* CALL_OUT_H__ */

7154
src/closure.c Normal file

File diff suppressed because it is too large Load Diff

144
src/closure.h Normal file
View File

@ -0,0 +1,144 @@
#ifndef CLOSURE_H__
#define CLOSURE_H__ 1
#include "driver.h"
#include "typedefs.h"
#include "bytecode.h"
#ifdef USE_NEW_INLINES
#include "svalue.h"
#endif /* USE_NEW_INLINES */
/* --- Types --- */
/* --- struct lambda_s: ---
*
* If the closure uses constant values, they are stored in an svalue[]
* right before the struct lambda and indexed from the end.
* For lfun closures, the context variables are stored after the
* lambda_s. If the lfun closure has no context variables, or for
* other kinds of closures the context[] part is not allocated at all.
*/
struct lambda_s
{
/* svalue_t values[]
*
* For lambda closures, the constant values used by the function
* which are indexed from the end. That means that value #x can
* be found at address ((svalue_t *)lambda_t)[-x-1].
*/
p_int ref; /* ref count */
object_t *ob;
/* Object the closure is bound to (for bound UNBOUND_LAMBDAs just
* during the execution of the lambda).
*/
object_t *prog_ob;
ptrdiff_t prog_pc;
/* Blueprint object and relative for the program creating this closure,
* or NULL. Since this information is error reporting purposes only,
* the lambda keeps a reference to the blueprint and not the program
* itself to not get in the way of swapping or other things.
*/
union /* Closure information: */
{
unsigned short var_index;
/* _IDENTIFIER: index in the variable table
*/
# define VANISHED_VARCLOSURE_INDEX ((unsigned short)-1)
/* Special value for vanished variable closures.
* TODO: it's tested with >=0 at places :-(,
*/
struct {
/* CLOSURE_LFUN */
object_t *ob; /* Originating object */
unsigned short index; /* Index in the object's function
* table */
program_t *inhProg; /* NULL or the program containing
* the function for closure
* referencing inherited functions
* (even if overloaded).
*/
unsigned short context_size; /* Number of context vars */
} lfun;
bytecode_t code[1];
/* LAMBDA and UNBOUND_LAMBDA closures: the function code, starting
* with uint8 'num_values' and continuing with FUNCTION_NUM_ARGS
* (which is where the fun_hdr_p will point to).
* 'num_values' is the size of the svalue[] preceeding the lambda;
* if it is 0xff, the actual size is stored in
* svalue[-0xff].u.number.
*/
# define LAMBDA_NUM_VALUES(p) EXTRACT_UCHAR((char *)p)
# define LAMBDA_NUM_ARGS(p) EXTRACT_SCHAR((char *)p + sizeof(char))
# define LAMBDA_NUM_VARS(p) (*((unsigned char *)((char *)p + 2*sizeof(char))))
# define LAMBDA_CODE(p) ((bytecode_p)((unsigned char *)p + 3*sizeof(char)))
lambda_t *lambda;
/* BOUND_LAMBDA: pointer to the UNBOUND_LAMBDA structure.
*/
} function;
#ifdef USE_NEW_INLINES
svalue_t context[ /* .lfun.context_size */ 1];
/* lfun-closure context variables, if any.
* Putting this array into the function.lfun somehow causes memory
* corruption because some lambda structures won't be allocated large
* enough.
*/
#endif
};
#define LAMBDA_VALUE_OFFSET \
(sizeof(svalue_t) + offsetof(lambda_t, function.code[1]))
/* Offset from the fun_hdr_p of a lambda closure to the first
* constant value (the one with index number 0).
*/
#ifndef USE_NEW_INLINES
#define SIZEOF_LAMBDA(num) sizeof(struct lambda_s)
#else /* USE_NEW_INLINES */
#define SIZEOF_LAMBDA(num) (sizeof(struct lambda_s) + (((int)num)-1) * sizeof(svalue_t))
#endif /* USE_NEW_INLINES */
/* size_t SIZEOF_LAMBDA(int num)
* Size of a lambda closure with <num> context variables.
*/
/* --- Prototypes --- */
extern long find_function(const string_t *name, const program_t *prog);
extern Bool closure_eq (svalue_t * left, svalue_t * right);
extern int closure_cmp (svalue_t * left, svalue_t * right);
extern void set_closure_user(svalue_t *svp, object_t *owner);
extern void replace_program_lambda_adjust(replace_ob_t *r_ob);
extern void closure_init_lambda (lambda_t * l, object_t * obj);
#ifndef USE_NEW_INLINES
extern void closure_literal(svalue_t *dest, int ix, unsigned short inhIndex);
extern void closure_lfun (svalue_t *dest, object_t *obj, program_t *prog, int ix, Bool raise_error);
extern lambda_t *closure_new_lambda (object_t * obj, Bool raise_error);
#else /* USE_NEW_INLINES */
extern lambda_t *closure_new_lambda (object_t * obj, unsigned short context_size, Bool raise_error);
extern void closure_lfun (svalue_t *dest, object_t *obj, program_t *prog, int ix, unsigned short num, Bool raise_error);
extern void closure_literal(svalue_t *dest, int ix, unsigned short inhIndex, unsigned short num);
#endif /* USE_NEW_INLINES */
extern void closure_identifier (svalue_t *dest, object_t * obj, int ix, Bool raise_error);
extern void free_closure(svalue_t *svp);
extern Bool is_undef_closure (svalue_t *sp);
extern void closure_lookup_lfun_prog ( lambda_t * l , program_t ** pProg , string_t ** pName , Bool * pIsInherited);
extern const char * closure_operator_to_string (int type);
extern const char * closure_efun_to_string (int type);
extern string_t * closure_location (lambda_t *l);
extern string_t *closure_to_string (svalue_t * sp, Bool compact);
extern svalue_t *v_bind_lambda(svalue_t *sp, int num_arg);
extern svalue_t *f_lambda(svalue_t *sp);
extern svalue_t *f_symbol_function(svalue_t *sp);
extern svalue_t *f_symbol_variable(svalue_t *sp);
extern svalue_t *f_unbound_lambda(svalue_t *sp);
extern void align_switch(bytecode_p pc);
#endif /* CLOSURE_H__ */

9428
src/comm.c Normal file

File diff suppressed because it is too large Load Diff

487
src/comm.h Normal file
View File

@ -0,0 +1,487 @@
#ifndef COMM_H__
#define COMM_H__ 1
#include "driver.h"
#include "typedefs.h"
#include <sys/types.h>
#ifdef USE_PTHREADS
# include <pthread.h>
#endif
#ifdef USE_MCCP
# include <zlib.h>
#endif
#include "simulate.h" /* callback_t for input_to_t */
#include "svalue.h"
#include "pkg-tls.h"
/* TODO: Make the following a separate "my-socket.h" include, also
* TODO:: to be used in access_check.h instead of comm.h.
*/
#ifdef SOCKET_HEADER
# include SOCKET_HEADER
#endif
#if !defined (SOCKET_LIB) && !defined(SOCKET_INC)
# include <sys/socket.h>
# ifdef _AIX
# include <sys/socketvar.h>
# endif
# include <netinet/in.h>
# include <arpa/inet.h>
# define SOCKET_T int
#endif /* SOCKET_LIB */
#ifndef MAX_SOCKET_PACKET_SIZE
# if defined(sgi) && defined(mips) && defined(unix)
/* Work around for an irix kernel bug that can leave the
* process unresponsive and unkillable.
*/
# define MAX_SOCKET_PACKET_SIZE 200
# else
# define MAX_SOCKET_PACKET_SIZE 1024 /* Wild guess. */
# endif /* irix */
#endif /* MAX_SOCKET_PACKET_SIXE */
/* --- IPv6 --- */
#ifdef USE_IPV6
/* For IPv6 we defined macros for the 'old' sockaddr member names
* which expand into the ipv6 names.
*/
#define sockaddr_in sockaddr_in6
#define sin_port sin6_port
#define sin_addr sin6_addr
#define sin_family sin6_family
#define s_addr s6_addr
#define in_addr in6_addr
#if defined(__APPLE__) && defined(__MACH__) && !defined(s6_addr32)
/* These are non-standard defines, and some OS don't offer them
* by default: OS-X
*/
# define s6_addr8 __u6_addr.__u6_addr8
# define s6_addr16 __u6_addr.__u6_addr16
# define s6_addr32 __u6_addr.__u6_addr32
#endif
#endif /* USE_IPV6 */
/* --- Macros --- */
/* 'Format string' to use with add_message() when sending
* a string_t* string to the player.
*/
#define FMT_STRING ((const char *)&add_message)
/* 'Format string' to use with add_message() when sending
* a string with binary characters and of fixed size
* to the player.
*/
#define FMT_BINARY (FMT_STRING+1)
/* --- Telnet Handling --- */
#define SEND_TELNET_COMMAND(TEXT) {\
sending_telnet_command = MY_TRUE;\
TEXT\
sending_telnet_command = MY_FALSE;\
}
/* Use this macro to safely send telnet commands with TEXT
*/
#ifdef DEBUG_TELNET
#define DT(x) printf("%s TDEBUG: ", time_stamp()); printf x
#define DTN(x) printf("%s TDEBUG: '%s' ", time_stamp(), get_txt(ip->ob->name)); printf x
#define DTF(x) printf x
#else
#define DT(x)
#define DTN(x)
#define DTF(x)
#endif
/* --- Types --- */
/* --- struct write_buffer_s: async write datastructure
*
* This data structure holds all the information for pending messages
* which are to be written by a background thread. The structure is
* allocated to the necessary length to hold the full message.
* The instances are kept in a linked list from the interactive_t
* structure.
*/
#ifdef USE_PTHREADS
struct write_buffer_s
{
struct write_buffer_s *next;
size_t length;
Bool compress; /* should the buffer get compressed by mccp? */
int errorno; /* After writing, the errno */
char buffer[1 /* .length */ ];
};
#endif
/* --- struct input_to_s: input_to() datastructure
*
* input-to structures describe a pending input_to() for a given
* interactive object. Every object can have one input-to pending, the
* pointer to the structure is stored in the interactive sentence structure.
*/
struct input_to_s {
input_to_t *next;
svalue_t prompt; /* the prompt, may be 0 */
char noecho; /* the requested "noecho" state */
Bool local; /* TRUE if a CHARMODE change is local only */
callback_t fun; /* The function to call, and its args */
};
/* --- struct interactive_s: an interactive connection
*
* The structure is linked to by a shadow sentence of the interactive
* object.
*
* When changing struct members, take care that you don't introduce
* unnecessary padding.
*/
struct interactive_s {
SOCKET_T socket; /* The socket structure */
object_t *ob; /* Points back to the associated object */
input_to_t *input_to; /* != NULL: defines function to be
called with next input line */
object_t *modify_command; /* modify_command() handler() */
svalue_t prompt; /* The prompt to print. */
struct sockaddr_in addr; /* Address of connected user */
CBool msg_discarded; /* True if an earlier msg had been discarded */
CBool set_input_to; /* True if input_to was set in this cycle */
CBool closing; /* True when closing this socket. */
CBool tn_enabled; /* True: telnet machine enabled */
#ifdef USE_EXPERIMENTAL
CBool is_binary; /* True: socket reads binary */
#endif
char do_close; /* Bitflags: Close this down; Proto-ERQ. */
char noecho; /* Input mode bitflags */
char tn_state; /* current state of telnet machine */
char save_tn_state; /* saved state of telnet machine */
CBool supress_go_ahead; /* Keep track of the WILL SGA negotiation state
* as some clients mix that up with DO SGA.
* Other than that, this is of no concern.
*/
CBool outgoing_conn; /* TRUE if the connection was created by
* net_connect().
*/
int text_end; /* first free char in buffer */
int command_start; /* used for charmode */
int command_end; /* where we are up to in player cmd buffer */
int tn_start; /* first char of pending telnet neg */
int tn_end; /* first char to check for telnet negotiation */
int32 chars_ready; /* amount of pure data available. In charmode
* this is the amount of data already echoed
* back to the sender. */
#ifdef USE_SNOOPING
interactive_t *snoop_on; /* whom we're snooping */
object_t *snoop_by; /* by whom we're snooped */
#endif
mp_int last_time; /* Time of last command executed */
long numCmds; /* Number of commands executed with the same
* .last_time */
long maxNumCmds; /* Maximum number of commands (char or line)
* to execute per second. A value < 0
* means 'unlimited'.
*/
int trace_level; /* Trace flags. 0 means no tracing */
string_t *trace_prefix; /* Trace only objects which have this string
as name prefix. NULL traces everything. */
int message_length; /* Current length of message in message_buf[] */
object_t *next_player_for_flush;
object_t *previous_player_for_flush;
/* Double linked list of all active user objects with data pending
* in message_buf[].
*/
long access_class;
/* represents a "cluster" where this player comes from
*/
char charset[32];
/* A bitflag array: every non-zero flag allows the corresponding
* character to be sent. Characters whose flag is 0 are excluded
* from the sent data.
*/
char combine_cset[32];
/* A bitflag array: all characters with their corresponding flag
* set to non-zero flag may be combined into one string in
* char-mode when received en-bloc anyway. Characters whose flag
* is 0 are always returned in charmode in separate strings.
* TODO: The code for these two thingies assume 8 Bits per character.
*/
CBool quote_iac;
CBool catch_tell_activ;
char gobble_char; /* Char to ignore at the next telnet_neg() */
char ts_data; /* Telnet suboption? */
char text[MAX_TEXT+2];
/* The receive buffer. It can contain two extra characters:
* a '\r' that is recognized only after another character is read,
* and a terminating '\0'.
*/
char message_buf[MAX_SOCKET_PACKET_SIZE];
/* The send buffer. */
#ifdef USE_MCCP
unsigned char compressing;
z_stream * out_compress;
unsigned char * out_compress_buf;
#endif
#ifdef USE_PTHREADS
/* The data exchange with the writer thread happens through two
* lists: write_first/write_last hands of data to write to
* the thread, written_first receives the written buffers.
* Reason for this 2-way exchange is that the writer thread
* must not call xfree().
* TODO: These two lists + one extra can be combined into
* TODO:: one list, plus two roving pointers into it.
* TODO:: In fact, once ptmalloc is really complete, the buffers
* TODO:: can be discarded immediately and the written_first list
* TODO:: becomes unnecessary.
*/
Bool flush_on_cleanup;
/* If set to TRUE at the time the thread is cancelled, all remaining
* pending data is sent to the socket (which is made non-blocking for
* this) as part of the cleanup.
*/
pthread_mutex_t write_mutex;
pthread_cond_t write_cond;
pthread_t write_thread;
struct write_buffer_s *write_first; /* List of buffers to write */
struct write_buffer_s *write_last;
unsigned long write_size;
struct write_buffer_s *write_current; /* Buffer currently written */
struct write_buffer_s *written_first; /* List of written buffers */
#endif
#ifdef USE_TLS
tls_session_t tls_session;
int tls_status;
# define TLS_INACTIVE 0 /* Session is not secure */
# define TLS_HANDSHAKING 1 /* TLS is being negotiated */
# define TLS_ACTIVE 2 /* Session is secure */
# define TLS_BROKEN 3 /* Error has occurred */
CBool tls_want_peer_cert;
# ifdef USE_EXPERIMENTAL
CBool tls_autodetect;
# endif
callback_t *tls_cb;
#endif
};
/* --- Bitflags and masks for interactive.noecho ---
*
* 'noecho' is a historical misnomer as it actually represents several
* input modes: echo/noecho, linemode/charmode, and ignore '!' escape.
* Echo and Charmode additionally distinguish between 'required'
* and 'granted' ('want yes' and 'yes').
*
* xxx_REQ is set when the lib wants this state (independend from telnet state)
* xxx is set when we sent out the appropirate negotiations
* xxx_ACK is set when the client agrees
*
* xxx xxx_ACK telnet state
* 0 0 NO
* 1 0 WANT YES
* 1 1 YES
* 0 1 WANT NO (not implemented)
*/
#define CHARMODE_REQ_TO_CHARMODE(x) ((x) << 2)
/* Transform {CHARMODE, NOECHO}_REQ into {CHARMODE, NOECHO}
*/
#define NOECHO_ACKSHIFT(x) ((x) << 2)
#define NOECHO_ACKRSHIFT(x) ((x) >> 2)
/* TODO: ???
*/
#define IGNORE_BANG 128
/* Disable input escape with leading '!'.
*/
#define NOECHO_REQ 1
/* noecho requested
*/
#define NOECHO /* 4 */ CHARMODE_REQ_TO_CHARMODE(NOECHO_REQ)
/* noecho active (requested via telnet negotiation)
*/
#define NOECHO_ACK /* 16 */ NOECHO_ACKSHIFT(NOECHO)
/* noecho negotiation complete (acknowledged)
* TODO: We need a _NACK flag, too, for when the negotiation is complete
* TODO:: but the client refused to go into NOECHO. For the time being
* TODO:: we might use (NOECHO_REQ|NOECHO) == (NOECHO_REQ) as check.
*/
#define NOECHO_STALE 64
/* Set prior to performing a noecho input, this bit causes the deactivation
* of noecho if still set after the input (ie if noecho was not requested
* again).
*/
#define NOECHO_MASK (NOECHO|NOECHO_ACK)
/* Mask for active noecho states.
*/
#define CHARMODE_REQ 2
/* Charmode requested
* The driver orients its behaviour according to this flag so that it
* can act correctly even before the negotiation is complete.
* Moreover, this flag serves as indicator that the input buffer
* variables are set up to 'charmode', so it should not be reset except
* through a call to set_noecho().
*/
#define CHARMODE /* 8 */ CHARMODE_REQ_TO_CHARMODE(CHARMODE_REQ)
/* Charmode active (requested via telnet negotiation)
*/
#define CHARMODE_ACK /* 32 */ NOECHO_ACKSHIFT(CHARMODE)
/* Charmode negotiation complete (acknowledged)
* TODO: We need a _NACK flag, too, for when the negotiation is complete
* TODO:: but the client refused to go into CHARMODE. For the time being
* TODO:: we can use (CHARMODE_REQ|CHARMODE) == CHARMODE_REQ as check.
*/
#define NOECHO_DELAYED 128
/* If NOECHO and CHARMODE is requested, we first try to establish
* CHARMODE and set this flag. If CHARMODE is acknoledged we try to
* negotiate for NOECHO. This modus operandi is enabled with SAVE_NOECHO.
* pro: If the user has a linemode-only client she is not left in
* useless NOECHO mode
* con: The NOECHO is delayed by the round trip time for the negotiation
* which could be imense on very slow lines.
* TODO: Need to defined SAVE_NOECHO in comm.c for this.
*/
#define CHARMODE_MASK (CHARMODE|CHARMODE_ACK)
/* Mask for active charmode states.
*/
/* --- Variables --- */
extern int num_pending_outconns; /* new! optimization! --lynX 2007 */
extern Bool sending_telnet_command;
extern interactive_t *all_players[MAX_PLAYERS];
extern int num_player;
extern char *message_flush;
extern char *domain_name;
extern long pthread_write_max_size;
#ifdef COMM_STAT
extern unsigned long add_message_calls;
extern unsigned long inet_packets;
extern unsigned long inet_volume;
extern unsigned long inet_packets_in;
extern unsigned long inet_volume_in;
#endif
/* --- Prototypes --- */
extern void initialize_host_name (const char *hname);
extern void initialize_host_ip_number(const char *, const char *);
extern void prepare_ipc(void);
extern void ipc_remove(void);
#ifdef USE_PTHREADS
extern void interactive_lock (interactive_t *ip);
extern void interactive_unlock (interactive_t *ip);
extern void interactive_cleanup (interactive_t *ip);
#else
extern void interactive_lock (interactive_t *ip UNUSED);
extern void interactive_unlock (interactive_t *ip UNUSED);
extern void interactive_cleanup (interactive_t *ip UNUSED);
#endif /* USE_PTHREADS */
extern void comm_cleanup_interactives (void);
extern void add_message VARPROT((const char *, ...), printf, 1, 2);
extern void flush_all_player_mess(void);
extern Bool get_message(char *buff, size_t *len);
extern void remove_interactive(object_t *ob, Bool force);
extern void set_noecho(interactive_t *i, char noecho, Bool local_change);
extern int find_no_bang (interactive_t *ip);
extern Bool call_function_interactive(interactive_t *i, char *str, size_t len);
extern void remove_all_players(void);
extern void print_prompt(void);
extern void init_telopts(void);
extern void mudlib_telopts(void);
extern svalue_t *v_input_to (svalue_t *sp, int num_arg);
extern svalue_t *f_query_udp_port(svalue_t *sp);
#ifdef ERQ_DEMON
extern void start_erq_demon(const char *suffix, size_t suffixlen);
extern svalue_t *f_attach_erq_demon(svalue_t *sp);
extern svalue_t *f_send_erq(svalue_t *sp);
#endif
extern size_t show_comm_status (strbuf_t * sbuf, Bool verbose);
extern void remove_stale_player_data (void);
extern void check_for_out_connections (void);
#ifdef GC_SUPPORT
extern void clear_comm_refs(void);
extern void count_comm_refs(void);
#endif /* GC_SUPPORT */
extern char *query_host_name(void);
extern char *get_host_ip_number(void);
extern svalue_t *f_query_idle(svalue_t *sp);
extern svalue_t *f_remove_interactive(svalue_t *sp);
#ifdef DEBUG
extern void count_comm_extra_refs(void);
#endif /* DEBUG */
extern svalue_t *f_send_udp(svalue_t *sp);
extern svalue_t *f_binary_message(svalue_t *sp);
extern svalue_t *f_exec(svalue_t *sp);
extern svalue_t *f_interactive(svalue_t *sp);
extern svalue_t *f_query_input_pending(svalue_t *sp);
extern svalue_t *f_query_ip_name(svalue_t *sp);
extern svalue_t *f_query_ip_number(svalue_t *sp);
extern svalue_t *f_query_mud_port(svalue_t *sp);
extern svalue_t *v_find_input_to (svalue_t *sp, int num_arg);
extern svalue_t *v_remove_input_to (svalue_t *sp, int num_arg);
extern svalue_t *f_input_to_info (svalue_t *sp);
extern svalue_t *f_set_buffer_size(svalue_t *sp);
extern svalue_t *f_get_combine_charset(svalue_t *sp);
extern svalue_t *f_set_combine_charset(svalue_t *sp);
extern svalue_t *f_get_connection_charset(svalue_t *sp);
extern svalue_t *f_set_connection_charset(svalue_t *sp);
extern svalue_t *f_set_prompt(svalue_t *sp);
extern svalue_t *f_users(svalue_t *sp);
extern svalue_t *f_get_max_commands (svalue_t *sp);
extern svalue_t *f_set_max_commands (svalue_t *sp);
extern svalue_t *f_enable_telnet (svalue_t *sp);
extern svalue_t *f_net_connect (svalue_t *sp);
#if defined(ACCESS_CONTROL)
extern void refresh_access_data(void (*add_entry)(struct sockaddr_in *, int, long*) );
#endif /* ACCESS_CONTROL */
#ifdef USE_SNOOPING
extern svalue_t *f_query_snoop(svalue_t *sp);
extern svalue_t *v_snoop(svalue_t *sp, int num_arg);
#endif
#endif /* COMM_H__ */

711
src/config.h.in Normal file
View File

@ -0,0 +1,711 @@
/* DO NOT EDIT!
*
* This file is created automatically by configure from the template
* in config.h.in.
*/
#ifndef CONFIG_H__
#define CONFIG_H__ 1
/* ----------- Commandline Argument Defaults ----------
* These options provide default settings for those options which can
* also be set on the commandline.
*/
/* Define COMPAT_MODE if you are using the 2.4.5 mudlib or one of its
* derivatives.
*/
@cdef_compat_mode@ COMPAT_MODE
/* The name of the master object.
*/
#define MASTER_NAME @val_master_name@
/* Define ALLOW_FILENAME_SPACES if the driver should accept space characters
* in filenames. If it is not defined, a hardcoded test for space characters
* is activated.
*/
@cdef_filename_spaces@ ALLOW_FILENAME_SPACES
/* --- Runtime limits --- */
/* This is the maximum array size allowed for one single array.
* If 0, any size is allowed.
*/
#define MAX_ARRAY_SIZE @val_max_array_size@
/* This is the maximum number of entries allowed for a single mapping.
* If 0, any size is allowed.
*/
#define MAX_MAPPING_KEYS @val_max_mapping_keys@
/* This is the maximum number of values held in a single mapping.
* If 0, any size is allowed.
*/
#define MAX_MAPPING_SIZE @val_max_mapping_size@
/* Max size of a file allowed to be read by 'read_file()'.
*/
#define READ_FILE_MAX_SIZE @val_read_file_max_size@
/* Define MAX_BYTE_TRANSFER to the number of bytes you allow to be read
* and written with read_bytes and write_bytes
*/
#define MAX_BYTE_TRANSFER @val_max_byte_transfer@
/* This is the maximum number of callouts allowed at one time.
* If 0, any number is allowed.
*/
#define MAX_CALLOUTS @val_max_callouts@
/* When USE_PTHREADS is used, define this to the maximum amount of data
* to be held pending for writing.
* A value of 0 means 'unlimited'.
*/
#define PTHREAD_WRITE_MAX_SIZE @val_pthreads_write_max_size@
/* --- Timing --- */
/* If an object is left alone for a certain time, then the
* function clean_up will be called. This function can do anything,
* like destructing the object. If the function isn't defined by the
* object, then nothing will happen.
*
* This time should be substantially longer than the swapping time.
*/
#define TIME_TO_CLEAN_UP @val_time_to_clean_up@
/* How long time until an unused object is swapped out.
* Machine with too many players and too little memory: 900 (15 minutes)
* Machine with few players and lot of memory: 10000
* Machine with infinite memory: 0 (never swap).
*/
#define TIME_TO_SWAP @val_time_to_swap@
#define TIME_TO_SWAP_VARIABLES @val_time_to_swap_variables@
/* How many seconds until an object is reset again.
* Set this value high if big system, otherwise low.
*/
#define TIME_TO_RESET @val_time_to_reset@
/* The granularity of alarm() calls.
* This is the granularity of the call_outs,
* and base granularity of heart_beat, reset und clean_up calls.
*/
#define ALARM_TIME @val_alarm_time@
/* The interval between heart beats.
*/
#define HEART_BEAT_INTERVAL @val_heart_beat_interval@
/* Shall all heart beats happen in the same time frame?
* (i.e. only every HEART_BEAT_INTERVAL seconds.)
*/
@cdef_synchronous_heart_beat@ SYNCHRONOUS_HEART_BEAT
/* --- Memory --- */
/* Reserve an extra memory area from malloc(), to free when we run out
* of memory to get some warning and start Armageddon.
* If this value is 0, no area will be reserved.
*/
#define RESERVED_USER_SIZE @val_reserved_user_size@
#define RESERVED_MASTER_SIZE @val_reserved_master_size@
#define RESERVED_SYSTEM_SIZE @val_reserved_system_size@
/* If MIN_MALLOCED is > 0, the gamedriver will reserve this amount of
* memory on startup for large blocks, thus reducing the large block
* fragmentation. The value therefore should be a significantly large
* multiple of the large chunk size.
* As a rule of thumb, reserve enough memory to cover the first couple
* of days of uptime.
*/
#define MIN_MALLOCED @val_min_malloced@
/* If MIN_SMALL_MALLOCED is > 0, the gamedriver will reserve this
* amount of memory on startup for small blocks, thus reducing the small block
* fragmentation. The value therefore should be a significantly large
* multiple of the small chunk size.
* As a rule of thumb, reserve enough memory to cover the first couple
* of days of uptime.
*/
#define MIN_SMALL_MALLOCED @val_min_small_malloced@
/* This value gives the upper limit for the total allocated memory
* (useful for systems with no functioning process limit).
* A value of 0 means 'unlimited'.
* TODO: This should be named 'MAX_MALLOC' - ditto in configure.
*/
#define MAX_MALLOCED @val_max_malloced@
/* --- Interpreter --- */
/* Define STRICT_EUIDS if the driver is to enforce the use of euids,
* ie. load_object() and clone_object() require the current object to
* have a non-zero euid.
*/
@cdef_strict_euids@ STRICT_EUIDS
/* Maximum number of evaluated nodes/loop.
* If this is exceeded, the current function is halted.
*/
#define MAX_COST @val_max_cost@
/* Define SHARE_VARIABLES if a clone's variables are to be assigned
* from the current blueprint's variables. Undefine it if clones
* should be initialized by __INIT().
*/
@cdef_share_variables@ SHARE_VARIABLES
/* --- Communication --- */
/* The input escape character.
*/
#define INPUT_ESCAPE @val_input_escape@
/* Define what port number the game is to use.
*/
#define PORTNO @val_portno@
/* Define this to the port on which the driver can receive UDP message.
* If set to -1, the port will not be opened unless the mud is given a valid
* port number on startup with the -u commandline option.
*/
#define UDP_PORT @val_udp_port@
/* Maximum numbers of ports the GD accepts connections to.
*/
#define MAXNUMPORTS @val_maxnumports@
/* Should code for the external request demon be included?
*/
@cdef_erq_demon@ ERQ_DEMON
/* Maximum sizes for an erq send or reply.
*/
#define ERQ_MAX_REPLY @val_erq_max_reply@
#define ERQ_MAX_SEND @val_erq_max_send@
/* Define this if you want IPv6 support (assuming that your host
* actually offers this.
*/
@cdef_use_ipv6@ USE_IPV6
/* If you want to use threads to write the data to the sockets
* define USE_PTHREADS.
*/
@cdef_use_pthreads@ USE_PTHREADS
/* ----------- Compilation Options ----------
* To change these options, the config.h must be recreated and the
* driver recompiled.
*/
/* Trace the most recently executed bytecode instructions?
*/
@cdef_trace_code@ TRACE_CODE
/* If using TRACE_CODE , how many instructions should be kept?
*/
#define TOTAL_TRACE_LENGTH @val_total_trace_length@
/* Runtime statistics:
* COMM_STAT: count number and size of outgoing packets.
* APPLY_CACHE_STAT: count number of hits and misses in the apply cache.
*/
@cdef_comm_stat@ COMM_STAT
@cdef_apply_cache_stat@ APPLY_CACHE_STAT
/* The name of the swapfile used by the driver to swap out objects (if
* enabled), relative to the mudlib directory. The driver will append
* '.<hostname>' to the file.
*/
#define SWAP_FILE @val_swap_file@
/* --- Memory --- */
/* Which memory manager to use. Possible defines are
* MALLOC_smalloc: Satoria's malloc. Fastest, uses the least memory,
* supports garbage collection.
* MALLOC_slaballoc: Slab allocator. Fastest, reduces fragmentation,
* supports garbage collection, not threadsafe.
* MALLOC_sysmalloc: the normal system malloc()
* MALLOC_ptmalloc: ptmalloc from www.malloc.de - threadsafe.
*/
#define MALLOC_@val_malloc@
/* Define this to let the memory allocator request memory from the system
* directly using sbrk() (assuming the system supports it).
* If not defined, the memory allocator will use malloc().
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
*/
@cdef_malloc_sbrk@ MALLOC_SBRK
/* Define this to annotate all allocations with a magic word to find
* simple misuses of memory (like multiple frees).
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
*/
@cdef_malloc_check@ MALLOC_CHECK
/* Define this to annotate all allocations with file:line of the driver
* source responsible for it.
*/
@cdef_malloc_trace@ MALLOC_TRACE
/* Define this to annotate all allocations with file:line of the lpc program
* responsible for it.
*/
@cdef_malloc_lpc_trace@ MALLOC_LPC_TRACE
/* Define this to log all calls to esbrk() (the system memory allocator).
* Works best if MALLOC_TRACE is defined.
* This define is useful if your mud keeps growing in total memory size
* instead of re-using the memory already allocated.
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
*/
@cdef_malloc_sbrk_trace@ MALLOC_SBRK_TRACE
/* --- Wizlist --- */
/* Where to save the WIZLIST information.
* If not defined, and neither given on the commandline, the driver will
* not read the WIZLIST file.
*/
@cdef_wizlist_file@ WIZLIST_FILE @val_wizlist_file@
/* --- Access Control --- */
/* #define ACCESS_CONTROL if you want the driver to do any access control.
* TODO: Make this a runtime option.
*/
@cdef_access_control@ ACCESS_CONTROL
/* file for access permissions data */
/* TODO: Make this a runtime option */
#define ACCESS_FILE @val_access_file@
/* logfile to show valid and rejected connections
* simple not define this for NO logs
* TODO: Make this a runtime option.
*/
@cdef_access_log@ ACCESS_LOG @val_access_log@
/* --- Language --- */
/* Define USE_PARSE_COMMAND if you want the efun parse_command().
*/
@cdef_use_parse_command@ USE_PARSE_COMMAND
/* Define USE_SET_LIGHT if you want the efun set_light() and the
* simple 2.4.5 light system.
*/
@cdef_use_set_light@ USE_SET_LIGHT
/* Define USE_SET_IS_WIZARD if you want the efun set_is_wizard().
*/
@cdef_use_set_is_wizard@ USE_SET_IS_WIZARD
/* Define USE_PROCESS_STRING if you want the efun process_string().
*/
@cdef_use_process_string@ USE_PROCESS_STRING
/* Define USE_SYSTEM_CRYPT if you want crypt() to be implemented by your
* operating system (assuming it offers this function). This makes your
* programm smaller and may even let you take advantage of improvements
* of your OS, but may also prohibit transporting encrypted date like
* passwords between different systems.
* Undefine USE_SYSTEM_CRYPT if you want to use the driver's portable
* crypt() implementation.
*/
@cdef_use_system_crypt@ USE_SYSTEM_CRYPT
/* Define this if you want MCCP (Mud Control Compression Protocol).
*/
@cdef_use_mccp@ USE_MCCP
/* Define this if you want TLS (Transport Layer Security) over Telnet.
*/
@cdef_use_tls@ USE_TLS
/* Define this if you want mySQL support (assuming that your host
* actually offers this.
*/
@cdef_use_mysql@ USE_MYSQL
/* Define this if you want PostgreSQL support (assuming that your host
* actually offers this.
*/
@cdef_use_pgsql@ USE_PGSQL
/* Define this if you want SQLite support (assuming that your host
* actually offers this.
*/
@cdef_use_sqlite@ USE_SQLITE
/* Define this if you want JSON support (assuming that your host
* actually offers this.
*/
@cdef_use_json@ USE_JSON
/* Define this if you want expat support (assuming that your host
* actually offers this.
*/
@cdef_use_expat@ USE_EXPAT
/* Define this if you want alist support.
*/
@cdef_use_alists@ USE_ALISTS
/* Define this if you want to allow call_other()s on arrays of objects.
*/
@cdef_lpc_array_calls@ USE_ARRAY_CALLS
/* Define this if you want PCRE instead of traditional regexps.
*/
@cdef_use_pcre@ USE_PCRE
/* Define this if you want to use builtin PCRE (ignored when PCRE
* is disabled as a whole).
*/
@cdef_use_builtin_pcre@ USE_BUILTIN_PCRE
/* Define this if you want the obsolete and deprecated efuns.
*/
@cdef_use_deprecated@ USE_DEPRECATED
/* --- Runtime limits --- */
/* Maximum size of a socket send buffer.
*/
#define SET_BUFFER_SIZE_MAX @val_set_buffer_size_max@
/* CATCH_RESERVED_COST is the default value added to the eval cost for the
* time executing code guarded by a catch() statement, so that an
* eval_cost-too-big error can still be caught and handled.
*
* To catch an eval_cost too big error in an object that called recursive
* master functions, CATCH_RESERVED_COST should be greater than
* MASTER_RESERVED_COST.
*/
#define CATCH_RESERVED_COST @val_catch_reserved_cost@
/* MASTER_RESERVED_COST is the total reserve available for master applies.
* It is halved for every recursion into another master apply.
*/
#define MASTER_RESERVED_COST @val_master_reserved_cost@ /* must be power of 2 */
/* TODO: Check that at runtime */
/* If this is defined, expensive operations like string additions
* receive additional evalcosts depending on the amount of data handled.
*/
@cdef_dynamic_costs@ DYNAMIC_COSTS
/* Define the maximum stack size of the stack machine. This stack will also
* contain all local variables and arguments.
*/
#define EVALUATOR_STACK_SIZE @val_evaluator_stack_size@
/* Define the maximum call depth for functions.
* MAX_USER_TRACE is used for for normal program execution, the full
* MAX_TRACE is only available in error handling.
*
* MAX_TRACE must be larger than MAX_USER_TRACE (check at compile time).
*/
#define MAX_USER_TRACE @val_max_user_trace@
#define MAX_TRACE @val_max_trace@
/* Maximum number of bits in a bit field. They are stored in printable
* strings, 6 bits per byte.
* The limit is more based on considerations of speed than memory
* consumption.
*/
#define MAX_BITS @val_max_bits@
/* Maximum number of players in the game.
*/
#define MAX_PLAYERS @val_max_players@
/* When uploading files, we want fast response; however, normal players
* shouldn't be able to hog the system in this way. Define ALLOWED_ED_CMDS
* to be the ratio of the no of ed cmds executed per player cmd.
*/
#define ALLOWED_ED_CMDS @val_allowed_ed_cmds@
/* TODO: ALLOWED_ED_CMDS: make this a runtime option */
/* --- Compiler --- */
/* Define the size of the compiler stack. This defines how complex
* expressions the compiler can parse. The value should be big enough.
*/
#define COMPILER_STACK_SIZE @val_compiler_stack_size@
/* Max number of local variables in a function.
*/
#define MAX_LOCAL @val_max_local@
/* Maximum size of an expanded preprocessor definition.
*/
#define DEFMAX @val_defmax@
/* --- Internal Tables --- */
/* Define the size of the shared string hash table. This number needn't
* be prime, probably between 1000 and 30000; if you set it to about 1/5
* of the number of distinct strings you have, you will get a hit ratio
* (number of comparisons to find a string) very close to 1, as found strings
* are automatically moved to the head of a hash chain. You will never
* need more, and you will still get good results with a smaller table.
* If the size is a power of two, hashing will be faster.
*/
#define HTABLE_SIZE @val_htable_size@
/* Object hash table size.
* Define this like you did with the strings; probably set to about 1/4 of
* the number of objects in a game, as the distribution of accesses to
* objects is somewhat more uniform than that of strings.
*/
#define OTABLE_SIZE @val_otable_size@
/* Define the size of the table of defines, reserved words, identifiers
* and efun names. Should be either several times smaller than HTABLE_SIZE
* or identical with it.
*/
#define ITABLE_SIZE @val_itable_size@
/* the number of apply_low cache entries will be 2^APPLY_CACHE_BITS.
*/
#define APPLY_CACHE_BITS @val_apply_cache_bits@
/* The parameters of the regular expression/result cache.
* The expression cache uses a hashtable of RXCACHE_TABLE entries.
* Undefine RXCACHE_TABLE to disable the all regexp caching.
*/
@cdef_rxcache_table@ RXCACHE_TABLE @val_rxcache_table@
/* --- Current Developments ---
* These options can be used to disable developments-in-progress if their
* code turns out to be interrrupting.
*/
/* Define this if you want structs supported.
*/
@cdef_use_structs@ USE_STRUCTS
/* Define this if you want the new inline closure syntax supported.
* (f-020528).
*/
@cdef_use_new_inlines@ USE_NEW_INLINES
/* --- Profiling ---
* For profiling of the VM instruction implementations, refer to the Makefile
*/
/* Enable usage statistics of VM instructions.
* For profiling of the VM instructions themselves, see the Profiling
* Options in the Makefile.
*/
@cdef_opcprof@ OPCPROF
#ifdef OPCPROF
/* With OPCPROF, the dump of the statistics include the names
* of the instructions.
*/
@cdef_verbose_opcprof@ VERBOSE_OPCPROF
#endif
/* --- Standard Debugging --- */
/* Enable basic run time sanity checks. This will use more time
* and space, but nevertheless you are strongly encouraged to keep
* it defined.
*/
@cdef_debug@ DEBUG
/* Enable debug output from the LPC compiler.
*/
@cdef_yydebug@ YYDEBUG
/* Disable inlining.
*/
@cdef_no_inlines@ NO_INLINES
/* Activate debug prints in the telnet machine.
*/
@cdef_debug_telnet@ DEBUG_TELNET
/* Activate allocation debug prints in the malloc module.
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
*/
@cdef_debug_malloc_allocs@ DEBUG_MALLOC_ALLOCS
/* The DEBUG level for the ERQ daemon:
* 0 : no debug output
* 1 : standard debug output
* 2 : verbose debug output
*/
#define ERQ_DEBUG @val_erq_debug@
/* --- Specific Debugging ---
* These options have been introduced to debug specific problems and will
* be removed again later.
*/
/* Enable the automatic data cleanup from the backend.
* TODO: Remove this macro once it is proven stable.
*/
#define NEW_CLEANUP
/* Log the details of the automatic data cleanup for each individual object.
* This is useful if the cleanup is suspected to hog the CPU.
* TODO: Remove this macro once it is proven stable.
*/
#undef LOG_NEW_CLEANUP
/* Log the details of the automatic data cleanup of all objects. This is
* useful if the cleanup is suspected to hog the CPU.
* TODO: Remove this macro once it is proven stable.
*/
#define LOG_NEW_CLEANUP_ALL
/* Enable the use of freelists in the malloc AVL nodes.
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
* TODO: Remove this macro once it is proven stable or if the change
* TODO:: didn't bring any advantages..
*/
#define USE_AVL_FREELIST
/* Order malloc large block freelists by address.
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
* TODO: Remove if it doesn't help with the fragmentation, as it uses up
* TODO:: a small, but measurable amount of time in the allocator.
*/
#define MALLOC_ORDER_LARGE_FREELISTS
/* Order slaballoc partial-slab freelists by number of free blocks.
* Supported by: MALLOC_slaballoc.
* TODO: Remove if it doesn't help with the fragmentation, as it uses up
* TODO:: a small, but measurable amount of time in the allocator.
*/
#define MALLOC_ORDER_SLAB_FREELISTS
/* Allow slaballoc to use multiples of DESIRED_SLAB_SIZE when creating
* new slabs.
*/
#define SLABALLOC_DYNAMIC_SLABS
/* Collect extended malloc statistics.
* Supported by: MALLOC_smalloc, MALLOC_slaballoc.
* TODO: Remove this macro or make it configurable.
*/
#define MALLOC_EXT_STATISTICS
/* Collected statistics about string comparisons.
* TODO: Remove this macro after we got our data.
*/
#define EXT_STRING_STATS
/* Trace changes to the tot_alloc_object and tot_alloc_object_size
* statistics, in order to find the status bugs (enables commandline
* option --check-object-stat). Will produce a decent amount of
* output on stderr.
*/
@cdef_check_object_stat@ CHECK_OBJECT_STAT
/* Activate total mapping size consistency check code. It has a small
* impact on the execution speed. This define was used to find
* the inaccuracy in the mapping statistic.
*/
@cdef_check_mapping_total@ CHECK_MAPPING_TOTAL
/* Activate object refcount check code. It will produce a decent
* amount of log output. It will also fatal() the driver as soon
* as it detects an inconsistency in the list of destructed objects.
*/
@cdef_check_object_ref@ CHECK_OBJECT_REF
/* Activate object referencing checking code during the GC. It will
* print error messages to gcout when an object or program is
* referenced as something else. No penalty for using.
* Requires MALLOC_TRACE to work. Incompatible with DUMP_GC_REFS.
*/
#ifdef MALLOC_TRACE
@cdef_check_object_gc_ref@ CHECK_OBJECT_GC_REF
#endif
/* Sometimes the GC stumbles over invalid references to memory
* blocks (namely 'Program referenced as something else'). Define
* this macro to get a detailed dump of all found references
* (Warning: LOTS of output!). Incompatible with CHECK_OBJECT_GC_REF.
*/
@cdef_dump_gc_refs@ DUMP_GC_REFS
/****** PSYCLPC ******/
/* maximum number of currently outgoing connections which are
* not yet fully established
* psyced needs a quite large value here
*/
#define MAX_OUTCONN @val_max_net_connects@
/* Size of each interactive socket's buffer for incoming data.
* This is also the maximum size for one command().
* For MUD use, this value used to be 2048 traditionally.
*/
#define MAX_TEXT @val_size_socket_buffer@
/* Why make comments in config.h if you're not supposed to edit it anyway?
* Here is the list of the new psyclpc flags.
* See elsewhere for explainations.
*
@cdef_backtrace_always@ BACKTRACE_ALWAYS
@cdef_use_paranoid_refs@ PARANOID_REFS
*/
@cdef_use_actions@ USE_ACTIONS
@cdef_use_authlocal@ USE_AUTHLOCAL
@cdef_use_builtin_editor@ USE_BUILTIN_EDITOR
@cdef_use_experimental@ USE_EXPERIMENTAL
@cdef_use_inventories@ USE_INVENTORIES
@cdef_use_ldmud_compatibility@ USE_LDMUD_COMPATIBILITY
@cdef_use_paranoia@ USE_PARANOIA
@cdef_use_restored_objects@ USE_RESTORED_OBJECTS
@cdef_use_shadowing@ USE_SHADOWING
@cdef_use_snooping@ USE_SNOOPING
@cdef_use_socket_limits@ USE_SOCKET_LIMITS
@cdef_use_srv@ USE_SRV
@cdef_use_swap@ USE_SWAP
/* Set up a configuration like LDMUD with a lot more debugging
* code in your regularely running driver than you will want.
* Of course you also have to set all the new use_something
* selectors to yes, or simply run ./configure as it stands.
*/
#ifdef USE_LDMUD_COMPATIBILITY
# ifdef DEBUG
# ifndef USE_PARANOIA
# define USE_PARANOIA
# endif
# endif
# define CHECK_REFS
# define USE_TRASH
# define VERBOSE
#endif
#endif /* CONFIG_H__ */

20134
src/configure vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,39 @@
# http://mantis.bearnip.com/view.php?id=475
Consider this code:
mixed x = m_allocate(100,2); x += ([2:3;4;5]);
mixed y = m_allocate(100,2); y = y + ([2:3;4;5]);
The first line results in an error, saying the mapping width doesn't match. The second line results in y containing mapping of width 3. As x is empty, the first line should work as well.
add_to_mapping() in mapping.c tests for empty mappings with
0 == m2->num_entries && NULL == m2->hash
For m_allocate-d mappings, hash is empty but not 0.
Why is the hash tested at all? 3.2 doesn't have that check.
Attachment: patch to remove the NULL == m[1,2]->hash tests
Index: mapping.c
===================================================================
--- mapping.c (revision 2306)
+++ mapping.c (working copy)
@@ -3352,7 +3352,7 @@
/* If one of the two mappings is empty, we can adjust its width
* after getting rid of all pending data blocks.
*/
- if (0 == m2->num_entries && NULL == m2->hash)
+ if (0 == m2->num_entries)
{
if (m2->cond != NULL)
{
@@ -3363,7 +3363,7 @@
}
m2->num_values = m1->num_values;
}
- else if (0 == m1->num_entries && NULL == m1->hash)
+ else if (0 == m1->num_entries)
{
if (m1->cond != NULL)
{

View File

@ -0,0 +1,80 @@
# http://mantis.bearnip.com/view.php?id=500
#
diff -ur ldmud-3.3.714/src/mstrings.c ldmud-3.3.714-zesstra/src/mstrings.c
--- ldmud-3.3.714/src/mstrings.c 2006-07-10 04:43:25.000000000 +0200
+++ ldmud-3.3.714-zesstra/src/mstrings.c 2007-02-25 15:56:17.000000000 +0100
@@ -179,22 +179,16 @@
#endif /* EXT_STRING_STATS */
/*-------------------------------------------------------------------------*/
-static INLINE whash_t
+/*
+whash_t
hash_string (const char * const s, size_t size)
-
-/* Compute the hash for string <s> of length <size> and return it.
+ * Compute the hash for string <s> of length <size> and return it.
* The result will always be non-zero.
+ * NOTE: The definition of the function is now in mstrings.h because it is
+ * also used in otable.c and the definition needs to be in every compilation
+ * unit which uses it.
*/
-{
- whash_t hash;
-
- hash = whashmem(s, size, MSTRING_HASH_LENGTH);
- if (!hash)
- hash = 1 << (sizeof (hash) * CHAR_BIT - 1);
- return hash;
-} /* hash_string() */
-
/*-------------------------------------------------------------------------*/
static INLINE whash_t
get_hash (string_t * pStr)
diff -ur ldmud-3.3.714/src/mstrings.h ldmud-3.3.714-zesstra/src/mstrings.h
--- ldmud-3.3.714/src/mstrings.h 2006-07-10 04:43:26.000000000 +0200
+++ ldmud-3.3.714-zesstra/src/mstrings.h 2007-02-25 15:52:32.000000000 +0100
@@ -117,6 +117,26 @@
/* --- Inline functions and macros --- */
+/*-------------------------------------------------------------------------*/
+static INLINE whash_t
+hash_string (const char * const s, size_t size)
+/* Compute the hash for string <s> of length <size> and return it.
+ * The result will always be non-zero.
+ * Needs to be in mstrings.h to be inlined because otable.c also uses it.
+ * NOTE: it is static so the compiler generates inline functions only visible
+ * in the compilation unit. Thus the linker does not bail out in case the
+ * compiler does not inline it and it is portable on systems not supporting inline.
+ */
+{
+ whash_t hash;
+
+ hash = whashmem(s, size, MSTRING_HASH_LENGTH);
+ if (!hash)
+ hash = 1 << (sizeof (hash) * CHAR_BIT - 1);
+ return hash;
+} /* hash_string() */
+/*-------------------------------------------------------------------------*/
+
#define mstr_mem_size(s) \
(sizeof(string_t) + (s)->size)
diff -ur ldmud-3.3.714/src/otable.c ldmud-3.3.714-zesstra/src/otable.c
--- ldmud-3.3.714/src/otable.c 2006-07-10 04:42:56.000000000 +0200
+++ ldmud-3.3.714-zesstra/src/otable.c 2007-02-25 16:12:12.000000000 +0100
@@ -51,10 +51,10 @@
#if !( (OTABLE_SIZE) & (OTABLE_SIZE)-1 )
# define ObjHash(s) (mstr_get_hash(s) & ((OTABLE_SIZE)-1) )
-# define ObjHashStr(s,len) (whashmem(s, len, MSTRING_HASH_LENGTH) & ((OTABLE_SIZE)-1) )
+# define ObjHashStr(s,len) (hash_string(s, len) & ((OTABLE_SIZE)-1) )
#else
# define ObjHash(s) (mstr_get_hash(s) % OTABLE_SIZE)
-# define ObjHashStr(s,len) (whashmem(s, len, MSTRING_HASH_LENGTH) % OTABLE_SIZE)
+# define ObjHashStr(s,len) (hash_string(s, len) % OTABLE_SIZE)
#endif
/* Hash the string <s> and compute the appropriate table index
*/

View File

@ -0,0 +1,105 @@
# http://mantis.bearnip.com/view.php?id=477
#
# another fine contribution by fufu. requires 'improve-statistics.patch'
int get_eval_number()
Return the current evaluation number. It's incremented for each top-level call. [...]
The intended purpose of this function is to find out if something has already been done for the current command, heart_beat, call_out or whatever. Control flow in mudlibs is often complicated and adding the necessary infrastructure to a mudlib to answer this question is error-prone and tedious. In the driver it's just a few lines of code.
Index: doc/efun/get_eval_number
===================================================================
--- doc/efun/get_eval_number (revision 0)
+++ doc/efun/get_eval_number (revision 0)
@@ -0,0 +1,17 @@
+SYNOPSIS
+ int get_eval_number()
+
+DESCRIPTION
+ Return the current evaluation number. It's incremented for each
+ top-level call. These are: commands, calls to heart_beat, reset,
+ or clean_up, and calls generated by call_out or input_to, master
+ applies triggered by external events, send_erq callbacks and the
+ calls to logon on player login.
+
+ The counter is a 32 bits counter so it can overflow occasionally.
+
+HISTORY
+ Since ldmud 3.3.372
+
+SEE ALSO
+ get_eval_cost()
Index: src/efuns.c
===================================================================
--- src/efuns.c (revision 2306)
+++ src/efuns.c (working copy)
@@ -8702,5 +8702,23 @@
return sp;
} /* f_utime() */
+/*-------------------------------------------------------------------------*/
+svalue_t *
+f_get_eval_number (svalue_t *sp)
+
+/* EFUN get_eval_number()
+ *
+ * Return the current evaluation number. It's incremented for each
+ * top-level call. These are: commands, calls to heart_beat, reset,
+ * or clean_up, and calls generated by call_out or input_to.
+ *
+ * The counter is a 32 bits counter so it will overflow occasionally.
+ */
+
+{
+ push_number(sp, eval_number);
+ return sp;
+} /* f_get_eval_number */
+
/***************************************************************************/
Index: src/func_spec
===================================================================
--- src/func_spec (revision 2306)
+++ src/func_spec (working copy)
@@ -772,6 +772,7 @@
int set_is_wizard(object, int default: F_CONST1);
#endif
+int get_eval_number();
/* Obsolete and deprecated functions */
Index: src/interpret.c
===================================================================
--- src/interpret.c (revision 2306)
+++ src/interpret.c (working copy)
@@ -697,7 +697,8 @@
#endif
- unsigned long total_evalcost;
+unsigned long eval_number; /* evaluation number. 32 bits - will overflow */
+unsigned long total_evalcost;
static struct timeval eval_begin;
/* Current total evalcost counter, and start of the evaluation.
*/
@@ -772,6 +773,7 @@
*/
{
+ eval_number++;
total_evalcost = 0;
if (gettimeofday(&eval_begin, NULL))
{
Index: src/interpret.h
===================================================================
--- src/interpret.h (revision 2306)
+++ src/interpret.h (working copy)
@@ -116,6 +116,7 @@
extern p_int apply_cache_miss;
#endif
+extern unsigned long eval_number;
extern unsigned long total_evalcost;
extern unsigned long last_total_evalcost;
extern struct timeval last_eval_duration;

View File

@ -0,0 +1,81 @@
# see also http://mantis.bearnip.com/view.php?id=476
This patch adds calls to mark_start_evaluation() and mark_end_evaluation() for external master applies, calls to logon() and erq_send callbacks. It also adds a mark_end_evaluation() in the global error handler
there are some other places which may or may not be toplevel evaluations:
telnet negotiation hook - I don't know which of the calls are toplevel and which might be triggered while executing code (say, by input_to)
noecho hook - same.
erq stop hook - called by attach_erq_demon, is it also called at the top level?
tls callbacks - didn't look further
Index: object.c
===================================================================
--- object.c (revision 2306)
+++ object.c (working copy)
@@ -921,12 +921,14 @@
object_t *save = current_object;
current_object = ob;
+ mark_start_evaluation();
ret = apply(STR_LOGON, ob, 0);
if (ret == 0)
{
errorf("Could not find %s() on the player %s\n", get_txt(STR_LOGON), get_txt(ob->name));
/* NOTREACHED */
}
+ mark_end_evaluation();
current_object = save;
} /* logon_object() */
Index: comm.c
===================================================================
--- comm.c (revision 2306)
+++ comm.c (working copy)
@@ -2860,8 +2860,10 @@
assigned_eval_cost = eval_cost = user->call_out_cost;
}
RESET_LIMITS;
+ mark_start_evaluation();
secure_callback_lambda(erqp, num_arg);
user->call_out_cost = eval_cost;
+ mark_end_evaluation();
if (!keep_handle || (ob->flags & O_DESTRUCTED))
{
free_svalue(erqp);
Index: backend.c
===================================================================
--- backend.c (revision 2306)
+++ backend.c (working copy)
@@ -449,6 +449,7 @@
/*
* We come here after errors, and have to clear some global variables.
*/
+ mark_end_evaluation();
clear_state();
flush_all_player_mess();
prevent_object_cleanup = MY_FALSE;
Index: interpret.c
===================================================================
--- interpret.c (revision 2306)
+++ interpret.c (working copy)
@@ -17334,6 +17334,8 @@
save_csp = csp;
if (setjmp(error_recovery_info.con.text))
{
+ if (external)
+ mark_end_evaluation();
secure_apply_error(save_sp - num_arg, save_csp, external);
printf("%s Error in master_ob->%s()\n", time_stamp(), get_txt(fun));
debug_message("%s Error in master_ob->%s()\n", time_stamp(), get_txt(fun));
@@ -17341,7 +17343,11 @@
}
else
{
+ if (external)
+ mark_start_evaluation();
result = sapply_int(fun, master_ob, num_arg, MY_TRUE, MY_FALSE);
+ if (external)
+ mark_end_evaluation();
}
/* Free the reserve if we used it */

View File

@ -0,0 +1,27 @@
# http://mantis.bearnip.com/view.php?id=500
#
diff -ur ldmud-3.3.714/src/simulate.c ldmud-3.3.714-zesstra/src/simulate.c
--- ldmud-3.3.714/src/simulate.c 2006-07-10 04:42:06.000000000 +0200
+++ ldmud-3.3.714-zesstra/src/simulate.c 2007-02-25 16:15:09.000000000 +0100
@@ -1762,6 +1762,13 @@
if ('/' == lname[0])
fatal("Improper filename '%s' passed to load_object()\n", lname);
#endif
+
+ // empty lnames may lead to a driver crash in enter_object_hash() if there
+ // exists a file '.c' in the root of the mudlib.
+ if ((name_length=strlen(lname)) <= 1) {
+ load_object_error("Illegal file to load (empty filename)", lname, chain);
+ /* NOTREACHED */
+ }
/* It could be that the passed filename is one of an already loaded
* object. In that case, simply return that object.
@@ -1776,7 +1783,6 @@
* the second because lname might be a buffer which is deleted
* during the compilation process.
*/
- name_length = strlen(lname);
name = alloca(name_length+2);
fname = alloca(name_length+4);
if (!name || !fname)

View File

@ -0,0 +1,12 @@
# http://mantis.bearnip.com/view.php?id=503
--- ldmud-3.3.714.orig/src/interpret.c 2006-07-10 04:44:33.000000000 +0200
+++ ldmud-3.3.714/src/interpret.c 2007-04-29 23:55:34.000000000 +0200
@@ -15165,6 +15165,8 @@
if (arg->type == T_NUMBER)
{
count = arg->u.number;
+ if (count<0 && !use_range)
+ ERRORF(("foreach() got %ld, expected a positive integer.\n",count));
vars_required = 1;
}
else if (arg->type == T_STRING)

169
src/driver.h Normal file
View File

@ -0,0 +1,169 @@
#ifndef DRIVER_H__
#define DRIVER_H__
/*------------------------------------------------------------------
* Global mandatory include file.
*
* It contains various global macros and declarations, and takes
* care of the proper inclusion of the configuration/portability
* include files.
*------------------------------------------------------------------
*/
#define __DRIVER_SOURCE__
#include "config.h"
/* TODO: Some TODO defines */
/* NO_NEGATIVE_RANGES: If defined, assignments to negative ranges
* like [4..2] are not allowed. However, they are useful at times
* and so this switch should be under control of a pragma or special
* syntactic construct. For now and for compatibility reasons, these
* ranges remain allowed.
*/
/* #undef NO_NEGATIVE_RANGES */
/*----------------------------------------------------------------*/
/* Verify some of the definitions in config.h */
/* Make sure that YYDEBUG is defined to 1 - just being defined
* is not sufficient.
*/
#if defined(YYDEBUG)
# undef YYDEBUG
# define YYDEBUG 1
#endif
#if !defined(MALLOC_smalloc) && !defined(MALLOC_sysmalloc) && !defined(MALLOC_ptmalloc) && ~defined(MALLOC_slaballoc)
# define MALLOC_slaballoc
#endif
/* Do we have full GC support? */
#if defined(MALLOC_smalloc) || defined(MALLOC_ptmalloc) || defined(MALLOC_slaballoc)
# define GC_SUPPORT 1
#endif
/* Do some of the selected packages require special treatment? */
/* SQLite in the threadsafe mode needs a normal malloc() */
#if defined(SBRK_OK) && defined(USE_SQLITE)
# undef SBRK_OK
#endif
/* PTHREADS need a normal malloc() */
#if defined(SBRK_OK) && (defined(USE_PTHREADS) || defined(SQLITE3_USES_PTHREADS))
# undef SBRK_OK
#endif
/* When we have allocation tracing, the allocator annotates every
* allocation with the source filename and line where the allocation
* occured. To allow the annotation of the allocations of higher structures
* like strings with the place where the string as such is allocated (and not
* the places in the string module), the following macros can be used
* to declare and pass the necessary information transparently:
*
* MTRACE_DECL: the declaration of the tracing arguments
* MTRACE_PASS: the tracing arguments when passed on to lower
* functions
* MTRACE_ARG: the tracing arguments on the toplevel call
*/
#ifdef MALLOC_TRACE
#define MTRACE_DECL , const char * malloc_trace_file, int malloc_trace_line
#define MTRACE_PASS , malloc_trace_file, malloc_trace_line
#define MTRACE_ARG , __FILE__, __LINE__
#else
#define MTRACE_DECL
#define MTRACE_PASS
#define MTRACE_ARG
#endif
/* To function properly, MALLOC_(LPC_)TRACE need to be able to
* test whether a memory block is free or not. This is reliably implemented
* by MALLOC_CHECK.
*/
#if (defined(MALLOC_TRACE) || defined(MALLOC_LPC_TRACE)) && !defined(MALLOC_CHECK)
# define MALLOC_CHECK
#endif
/* This one is for backwards compatibility with old config.hs */
#if defined(NATIVE_MODE) && !defined(STRICT_EUIDS)
# define STRICT_EUIDS
#elif defined(COMPAT_MODE)
# undef STRICT_EUIDS
#endif
/* The string table is shadowed only in DEBUG mode */
#if !defined(DEBUG) && defined(CHECK_STRINGS)
# undef CHECK_STRINGS
#endif
/* The ALARM and HEART_BEAT time need to be at least 1. */
#if !defined(ALARM_TIME)
#define ALARM_TIME 1
#elif ALARM_TIME < 1
#undef ALARM_TIME
#define ALARM_TIME 1
#endif
#if !defined(HEART_BEAT_INTERVAL)
#define HEART_BEAT_INTERVAL 1
#elif HEART_BEAT_INTERVAL < 1
#undef HEART_BEAT_INTERVAL
#define HEART_BEAT_INTERVAL 1
#endif
/* Define some macros needed in the headers included from ../mudlib/sys */
#ifdef USE_IPV6
# define __IPV6__
#endif
/* Include the portability headers */
#include "port.h"
/* TODO: this ctype-stuff might go into lex.h (impl in efun_defs.c) */
#define _MCTe 0x01 /* escaped character in save/restore object. */
#define _MCTd 0x02 /* numeric digit */
#define _MCTt 0x04 /* delimiters in save/restore object. */
#define _MCTs 0x10 /* whitespace EXCLUDING '\n' */
#define _MCTx 0x40 /* hexadecimal */
#define _MCTa 0x80 /* alphanumeric or '_' */
extern unsigned char _my_ctype[];
#define isescaped(c) (_my_ctype[(unsigned char)(c)]&_MCTe)
#define issavedel(c) (_my_ctype[(unsigned char)(c)]&_MCTt)
#define isalunum( c) (_my_ctype[(unsigned char)(c)]&_MCTa)
#define lexdigit( c) (_my_ctype[(unsigned char)(c)]&_MCTd)
#ifndef MAXINT
# define MAXINT (0x7fffffffU)
#endif
/* A define to point out empty loop bodies. */
#define NOOP
/* A macro to wrap statements */
#define MACRO(x) do { x ; } while(0)
/* Determine the minimum of two values.
* Some systems define this in system includes.
*/
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif /* MIN */
#endif /* DRIVER_H__ */

432
src/dumpstat.c Normal file
View File

@ -0,0 +1,432 @@
/*---------------------------------------------------------------------------
* Gamedriver - Dump object statistics.
*
*---------------------------------------------------------------------------
* Function to compute the memory usage of objects and dump their
* statistics.
*---------------------------------------------------------------------------
*/
#include "driver.h"
#include "typedefs.h"
#include <stdio.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <time.h>
#include "dumpstat.h"
#include "array.h"
#include "closure.h"
#include "exec.h"
#include "filestat.h"
#include "instrs.h" /* F_RETURN, F_RETURN0 for overhead computation */
#include "mapping.h"
#include "mstrings.h"
#include "object.h"
#include "ptrtable.h"
#include "simulate.h"
#include "stdstrings.h"
#ifdef USE_STRUCTS
#include "structs.h"
#endif /* USE_STRUCTS */
#include "svalue.h"
#include "xalloc.h"
/*-------------------------------------------------------------------------*/
static size_t svalue_size(svalue_t *, mp_int *); /* forward */
/* Auxiliary structure for counting a mapping */
struct svalue_size_locals
{
mp_uint composite; /* Return: total composite memory usage of all elmts */
mp_uint total; /* Return: total memory usage of all elmts */
int num_values; /* Passed: width of the mapping */
};
/*-------------------------------------------------------------------------*/
static struct pointer_table *ptable;
/* The pointer_table to register all arrays and mappings.
*/
/*-------------------------------------------------------------------------*/
static void
svalue_size_map_filter (svalue_t *key, svalue_t *values, void *extra)
/* Called for all keys in a mapping, it counts the size of the values
* and returns the total in extra->num_values.
*/
{
struct svalue_size_locals *locals;
mp_int total;
int i;
locals = (struct svalue_size_locals*)extra;
locals->composite += svalue_size(key, &total);
locals->total += total;
for(i = locals->num_values; --i >= 0; )
{
locals->composite += svalue_size(values++, &total) + sizeof(svalue_t);
locals->total += total + sizeof(svalue_t);
}
}
/*-------------------------------------------------------------------------*/
static size_t
svalue_size (svalue_t *v, mp_int * pTotal)
/* Compute the memory usage of *<v> (modified to reflect data sharing),
* calling svalue_size() recursively if necessary, and return it.
* The size of *v itself is not included.
* *<pUnshared> and *<pShared> are set to the total unshared and shared
* datasize.
*/
{
mp_int i, composite, total, overhead;
assert_stack_gap();
*pTotal = 0;
total = overhead = composite = 0;
switch(v->type)
{
case T_OBJECT:
case T_NUMBER:
case T_FLOAT:
return 0;
case T_STRING:
case T_SYMBOL:
*pTotal = mstr_mem_size(v->u.str);
return *pTotal / v->u.str->info.ref;
case T_MAPPING:
{
struct svalue_size_locals locals;
if (NULL == register_pointer(ptable, v->u.map) ) return 0;
overhead = (mp_uint)mapping_overhead(v->u.map);
locals.total = 0;
locals.composite = 0;
locals.num_values = v->u.map->num_values;
walk_mapping(v->u.map, svalue_size_map_filter, &locals);
*pTotal = locals.total + overhead;
return (overhead + locals.composite) / v->u.map->ref;
}
case T_POINTER:
case T_QUOTED_ARRAY:
{
if (v->u.vec == &null_vector) return 0;
if (NULL == register_pointer(ptable, v->u.vec) ) return 0;
overhead = sizeof *v->u.vec - sizeof v->u.vec->item +
sizeof(svalue_t) * v->u.vec->size + sizeof(char *);
for (i=0; i < (mp_int)VEC_SIZE(v->u.vec); i++) {
composite += svalue_size(&v->u.vec->item[i], &total);
*pTotal += total;
}
*pTotal += overhead;
return (overhead + composite) / v->u.vec->ref;
}
#ifdef USE_STRUCTS
case T_STRUCT:
{
struct_t *st = v->u.strct;
if (NULL == register_pointer(ptable, st) ) return 0;
overhead = sizeof *st - sizeof st->member
+ sizeof(svalue_t) * struct_size(st);
for (i=0; i < (mp_int)struct_size(st); i++) {
composite += svalue_size(&st->member[i], &total);
*pTotal += total;
}
*pTotal += overhead;
return (overhead + composite) / st->ref;
}
#endif /* USE_STRUCTS */
case T_CLOSURE:
{
int num_values;
svalue_t *svp;
lambda_t *l;
if (!CLOSURE_MALLOCED(v->x.closure_type)) return 0;
if (!CLOSURE_REFERENCES_CODE(v->x.closure_type))
{
#ifdef USE_NEW_INLINES
if (v->x.closure_type == CLOSURE_LFUN)
composite = SIZEOF_LAMBDA(v->u.lambda->function.lfun.context_size);
else /* CLOSURE_IDENTIFIER || CLOSURE_PRELIMINARY */
composite = sizeof *v->u.lambda;
composite += sizeof(char *);
#else
/* CLOSURE_LFUN || CLOSURE_IDENTIFIER || CLOSURE_PRELIMINARY */
composite = sizeof *v->u.lambda + sizeof(char *);
#endif
*pTotal = composite;
return composite / v->u.lambda->ref;
}
/* CLOSURE_LAMBDA */
composite = overhead = 0;
l = v->u.lambda;
if (v->x.closure_type == CLOSURE_BOUND_LAMBDA)
{
total = sizeof *l - sizeof l->function + sizeof l->function.lambda;
*pTotal += total;
composite += total / l->ref;
l = l->function.lambda;
}
num_values = EXTRACT_UCHAR(&l->function.code[0]);
if (num_values == 0xff)
num_values = ((svalue_t *)l)[-0xff].u.number;
svp = (svalue_t *)l - num_values;
if (NULL == register_pointer(ptable, svp)) return 0;
overhead = sizeof(svalue_t) * num_values + sizeof (char *);
{
bytecode_p p = &l->function.code[2];
do {
++p;
switch(GET_CODE(p)) {
case F_RETURN:
case F_RETURN0:
break;
default:
continue;
}
break;
} while (1);
overhead += (p - (bytecode_p)l + (sizeof(bytecode_p) - 1))
& ~(sizeof(bytecode_p) - 1);
}
while (--num_values >= 0)
{
composite += svalue_size(svp++, &total);
*pTotal += total;
}
*pTotal += overhead;
return (overhead + composite) / l->ref;
}
default:
fatal("Illegal type: %d\n", v->type);
}
/*NOTREACHED*/
return 0;
}
/*-------------------------------------------------------------------------*/
mp_int
data_size (object_t *ob, mp_int * pTotal)
/* Compute the memory usage (modified to reflect shared data use)
* of the data held by object <ob> and return it.
* If the object is swapped out or has no variables, return 0.
*
* If <pTotal> is given, *<pTotal> is set to the raw datasize.
*/
{
mp_int total = sizeof(p_int); /* smalloc overhead */
int i;
svalue_t *svp;
if (pTotal != NULL)
*pTotal = 0;
if (ob->flags & O_SWAPPED || !(i = ob->prog->num_variables) )
return 0;
ptable = new_pointer_table();
if (!ptable)
errorf("(dumpstat) Out of memory for new pointer table.\n");
for (svp = ob->variables; --i >= 0; svp++)
{
mp_int tmp;
total += svalue_size(svp, &tmp) + sizeof (svalue_t);
if (pTotal != NULL)
*pTotal += tmp + sizeof(svalue_t);
}
free_pointer_table(ptable);
return total;
} /* data_size() */
/*-------------------------------------------------------------------------*/
mp_int
program_string_size (program_t *prog, mp_int * pOverhead, mp_int * pData)
/* Compute the composite data size of all strings in program <prog>
* which must be swapped in.
* Set *<pOverhead> to the size of the overhead in the program structure,
* and *<pData> to the raw data size of the strings.
*/
{
int i;
mp_int rc, data;
rc = data = 0;
for (i = prog->num_strings; i--; )
{
string_t * str = prog->strings[i];
mp_int size;
size = mstr_mem_size(str);
data += size;
rc += size / str->info.ref;
}
*pOverhead = prog->num_strings * sizeof(char *);
*pData = data;
return rc;
} /* program_string_size() */
/*-------------------------------------------------------------------------*/
Bool
dumpstat (string_t *fname)
/* This function dumps statistics about all listed objects into the file
* $MUDLIB/<fname>. It is called by the command parser or from debug_info.
* Return TRUE on success, FALSE if <fname> can't be written.
*/
{
FILE *f;
object_t *ob;
static char *swapstrings[] =
{"", "PROG SWAPPED", "VAR SWAPPED", "SWAPPED", };
fname = check_valid_path(fname, current_object, STR_OBJDUMP, MY_TRUE);
if (!fname)
return MY_FALSE;
f = fopen(get_txt(fname), "w");
if (!f)
{
free_mstring(fname);
return MY_FALSE;
}
FCOUNT_WRITE(get_txt(fname));
for (ob = obj_list; ob; ob = ob->next_all)
{
mp_int compsize, totalsize, overhead;
char timest[21];
struct tm *tm;
#ifdef DEBUG
if (ob->flags & O_DESTRUCTED) /* TODO: Can't happen */
continue;
#endif
compsize = data_size(ob, &totalsize);
if (!O_PROG_SWAPPED(ob)
&& (ob->prog->ref == 1 || !(ob->flags & (O_CLONE|O_REPLACED))))
{
overhead = ob->prog->total_size;
}
else
{
overhead = 0;
}
overhead += sizeof (object_t);
fprintf(f, "%-20s %5ld (%5ld) ref %2ld %s "
, get_txt(ob->name)
, compsize + overhead, totalsize + overhead
, ob->ref
, ob->flags & O_HEART_BEAT ? "HB" : " "
);
#ifdef USE_INVENTORIES
if (ob->super)
fprintf(f, "%s ", get_txt(ob->super->name));
else
#endif
fprintf(f, "-- ");
if (ob->gigaticks)
fprintf(f, " (%lu%09lu)", ob->gigaticks, ob->ticks);
else
fprintf(f, " (%lu)", ob->ticks);
fprintf(f, " %s",
swapstrings[(O_PROG_SWAPPED(ob)?1:0) | (O_VAR_SWAPPED(ob)?2:0)]
);
tm = localtime((time_t *)&ob->load_time);
strftime(timest, sizeof(timest)-1, "%Y.%m.%d-%H:%M:%S", tm);
fprintf(f, " %s\n", timest);
}
fclose(f);
free_mstring(fname);
return MY_TRUE;
} /* dumpstat() */
/*-------------------------------------------------------------------------*/
Bool
dumpstat_dest(string_t *fname)
/* this function dumps statistics about all destructed objects into the file
* $MUDLIB/<fname>. It is called by the commandparser and by debug_info().
* Return TRUE on success, FALSE if <fname> can't be written.
*/
{
FILE *f;
object_t *ob;
fname = check_valid_path(fname, current_object, STR_OBJDUMP, MY_TRUE);
if (!fname)
return MY_FALSE;
f = fopen(get_txt(fname), "w");
if (!f)
{
free_mstring(fname);
return MY_FALSE;
}
FCOUNT_WRITE(get_txt(fname));
for (ob = newly_destructed_objs; ob; ob = ob->next_all)
{
#ifdef DEBUG
if (!(ob->flags & O_DESTRUCTED)) /* TODO: Can't happen */
continue;
#endif
fprintf(f, "%-20s ref %2ld NEW\n"
, get_txt(ob->name)
, ob->ref
);
}
for (ob = destructed_objs; ob; ob = ob->next_all)
{
#ifdef DEBUG
if (!(ob->flags & O_DESTRUCTED)) /* TODO: Can't happen */
continue;
#endif
fprintf(f, "%-20s ref %2ld\n"
, get_txt(ob->name)
, ob->ref
);
}
fclose(f);
free_mstring(fname);
return MY_TRUE;
} /* dumpstat_dest() */
/***************************************************************************/

12
src/dumpstat.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef DUMPSTAT_H__
#define DUMPSTAT_H__ 1
#include "driver.h"
#include "typedefs.h"
extern mp_int data_size (object_t *ob, mp_int * pTotal);
extern mp_int program_string_size (program_t *prog, mp_int * pOverhead, mp_int * pData);
extern Bool dumpstat(string_t *name);
extern Bool dumpstat_dest(string_t *name);
#endif /* DUMPSTAT_H__ */

Some files were not shown because too many files have changed in this diff Show More