From: Richard W.M. Jones Date: Fri, 25 Apr 2014 10:39:16 +0000 (+0100) Subject: Add to git. X-Git-Url: http://git.annexia.org/?p=dlife.git;a=commitdiff_plain;h=HEAD Add to git. --- 0aec1163718450d8bfd64e42b053940a742e031a diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..d43da9b --- /dev/null +++ b/.cvsignore @@ -0,0 +1,22 @@ +Makefile.in +acinclude.m4 +aclocal.m4 +config.h.in +configure +dlife.spec +dlife-*.tar.gz +index.html +dlife_client.pl +dlife_server.pl +install-sh +missing +mkinstalldirs +stamp-h.in +config.cache +config.h +config.log +config.status +dlife_soup +stamp-h +Makefile +.deps diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..a576e60 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,5 @@ +Richard Jones + * Main author and maintainer. + +Falk Hueffner + * Contributed Debian package. diff --git a/Build b/Build new file mode 100755 index 0000000..36526ba --- /dev/null +++ b/Build @@ -0,0 +1,57 @@ +#!/bin/sh - +# DLIFE (C) 2000 Richard W.M. Jones +# and other authors listed in the ``AUTHORS'' file. +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id: Build,v 1.1 2002/04/05 17:02:25 rich Exp $ + +# This is a highly specialized build script for my machine. You will +# probably need to change this substantially to be appropriate for +# your environment. +# +# Please note also that you normally only ever run this script if you +# have changed something about the build process itself -- for example +# if you have changed ``configure.in'' or one of the ``Makefile.am'' +# files. If you just want to do a normal rebuild after changing a +# source file, all you need to do is: +# +# make && make install +# +# - RWMJ 1999/12/27. + +set -e +set -v + +: Make clean +make distclean ||: + +: Rebuilding autoconf/automake files +aclocal +autoheader +automake +autoconf + +mkdir -p $HOME/.build/{usr/share/doc,etc/cron.d,etc/init.d,var} ||: + +: Configure. +CFLAGS="-O" \ +./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var \ + --disable-user-check + +: Build. +make + +: Now run 'make install' as root. diff --git a/Build.local b/Build.local new file mode 100755 index 0000000..98f2fa5 --- /dev/null +++ b/Build.local @@ -0,0 +1,62 @@ +#!/bin/sh - +# DLIFE (C) 2000 Richard W.M. Jones +# and other authors listed in the ``AUTHORS'' file. +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id: Build.local,v 1.2 2002/04/05 17:02:25 rich Exp $ + +# This is a highly specialized build script for my machine. You will +# probably need to change this substantially to be appropriate for +# your environment. +# +# Please note also that you normally only ever run this script if you +# have changed something about the build process itself -- for example +# if you have changed ``configure.in'' or one of the ``Makefile.am'' +# files. If you just want to do a normal rebuild after changing a +# source file, all you need to do is: +# +# make && make install +# +# - RWMJ 1999/12/27. + +set -e +set -v + +: Make clean +make distclean ||: + +: Rebuilding autoconf/automake files +aclocal +autoheader +automake +autoconf + +mkdir -p $HOME/.build/{usr/share/doc,etc/cron.d,etc/init.d,var} ||: + +: Configure. +CFLAGS="-O" \ +./configure \ + --prefix=$HOME/.build/usr \ + --sysconfdir=$HOME/.build/etc \ + --localstatedir=$HOME/.build/var + +: Build. +make + +: Install in local build directory +make NO_CHOWN=1 install + +: Now run it with: $HOME/.build/usr/bin/dlife_soup diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..eeb586b --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, 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 software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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. + + + Copyright (C) 19yy + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Changelog b/Changelog new file mode 100644 index 0000000..77f7547 --- /dev/null +++ b/Changelog @@ -0,0 +1,9 @@ +2002-12-10 Nix + + * main.c (main): Use LOG_DAEMON, not LOG_USER. + * main.c (detect_nr_cpus): New for SPARC/Linux. + + * cell.c (run_thread): Use syslog(), not printf(). + * cell.c (cell_state_load): Likewise. + * cell.c (_cell_fixup_soup_ref): Likewise. + * cell.c (save_cell_in_outgoing): Likewise. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..a8b6661 --- /dev/null +++ b/INSTALL @@ -0,0 +1,106 @@ +Distributed Artificial Life (DLIFE) Installation Instructions +------------------------------------------------------------- + +Prerequisites +------------- + +For security reasons, all programs run as user/group dlife/dlife. Therefore +in order to be able to install this program, you must first create a user +and group called `dlife'. On a typical Linux system you will need to +do this, as root, before installing: + + /usr/sbin/groupadd dlife + /usr/sbin/useradd -g dlife -M dlife + +You will need the following Perl packages installed. Get them from +CPAN (http://www.cpan.org/) or one of its mirrors, or else get RPMs +from http://dlife.annexia.org/files/ . + + libnet, HTML-Parser, URI, MIME-Base64, Digest-MD5, libwww-perl, + Getopt-Long + +Warning to non-Red Hat users +---------------------------- + +The current installation is very Red Hat / Debian specific. It +installs files under /etc/cron.d/ and /etc/init.d/ directories, which +probably only exist on Red Hat or Debian machines. It would be nice to +have a way to determine where these directories are and to +automagically install cron jobs and rc files in the appropriate +places. Can anyone help me with this? + +Building and installing the client from source +---------------------------------------------- + +Configure the software: + + ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var + +Check that the software is going to be installed in the right +places. On my Red Hat Linux boxen, I get: + + checking for crontab directory... /etc/cron.d + checking for rc directory... /etc/init.d + checking spool directory... /var/spool/dlife + checking config directory... /etc/dlife + +Build it: + + make + +Install it (as root): + + make install + +To start up the software, run the following command as root: + + /etc/init.d/dlife.rc + +If all went well, then you should see one of more ``dlife_soup'' +processes running in top. (There should be one process for each +CPU on your machine). + +To make the dlife client start up every time you reboot the +computer, do as root: + + /sbin/chkconfig --add dlife.rc + +A cron job is set to run every hour which exchanges cells with +your local dlife server. By default it runs at 5 minutes past +the hour, but to avoid causing load spikes on dlife servers at +this time, it's best to edit the cron script and change the +time at which it runs. This script is here: + + /etc/cron.d/dlife_client.cron + +If you're running behind a firewall, then you may want to run a +server (see next section). In that case, you need to edit the +following file to list the location of your server(s): + + /etc/dlife/client.conf + +Building and installing the server from source +---------------------------------------------- + +Follow the process above, as if you were installing the client. + +Edit /etc/inetd.conf and add the following line: + + 5904 stream tcp nowait root /usr/sbin/tcpd /usr/bin/dlife_server.pl + +Restart inetd: + + killall -HUP inetd + +Building RPMs +------------- + +To build RPMs from the sources: + + ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var \ + --disable-user-check + make + make dist + rpm -ta --clean dlife-X.Y.Z.tar.gz + +(where X.Y.Z is the current version of dlife). diff --git a/Makefile+ b/Makefile+ new file mode 100644 index 0000000..25e364b --- /dev/null +++ b/Makefile+ @@ -0,0 +1,108 @@ +# -*- Makefile -*- +# +# This is a make+ file. Make+ is a set of scripts which enhance GNU +# make and let you build RPMs, and other package types with just one +# control file. To build this package you will need to download make+ +# from this site: http://www.annexia.org/freeware/makeplus/ + +PACKAGE := dlife +VERSION_MAJOR := 1 +VERSION_MINOR := 1.0 +VERSION := $(VERSION_MAJOR).$(VERSION_MINOR) + +SUMMARY := Distributed artificial life +COPYRIGHT := GPL +AUTHOR := Richard W.M. Jones + +define DESCRIPTION +Distributed Artificial Life is a package for joining your +computer to a network of computers running a large artificial +life simulation. +endef + +RPM_REQUIRES := perl-libwww-perl, perl >= 5.004, vixie-cron, SysVinit +RPM_GROUP := Applications/Internet + +spooldir = $(localstatedir)/spool/dlife +confdir = $(sysconfdir)/dlife +crondir = $(sysconfdir)/cron.d +rcdir = $(sysconfdir)/init.d + +CFLAGS += -Wall -Werror -g -O2 \ + -DCONFDIR=\"$(confdir)\" \ + -DSPOOLDIR=\"$(spooldir)\" +#LIBS += + +ifdef ENABLE_CHECK +CFLAGS += -DCHECK=1 +endif + +ifdef ENABLE_PROFILE +CFLAGS += -pg +endif + +DOCS := $(srcdir)/AUTHORS $(srcdir)/INSTALL $(srcdir)/README \ + $(srcdir)/archproc.gif $(srcdir)/archproc.fig \ + $(srcdir)/archref.html $(srcdir)/index.html \ + $(srcdir)/machineref.html + +OBJS := cell.o crc.o exec.o image.o load.o main.o random.o soup.o state.o + +all: build + +configure: + $(MP_CONFIGURE_START) + $(MP_CHECK_HEADERS) assert.h dirent.h errno.h fcntl.h grp.h pwd.h \ + signal.h stddef.h stdint.h string.h sys/param.h sys/types.h \ + syslog.h time.h unistd.h + $(MP_CHECK_FUNCS) closedir getpwnam getuid initgroups nice opendir \ + openlog readdir setgid setuid syslog +ifndef DISABLE_USER_CHECK +# $(MP_CHECK_USER_GROUP) dlife dlife +endif + $(MP_CONFIGURE_END) + +build: dlife_soup + +dlife_soup: $(OBJS) + $(CC) $(CFLAGS) $^ $(LIBS) -o $@ + +test: + +install: + install -d $(DESTDIR)$(bindir) + install -d $(DESTDIR)$(docdir) + install -d $(DESTDIR)$(spooldir) + install -d $(DESTDIR)$(spooldir)/incoming + install -d $(DESTDIR)$(spooldir)/outgoing + install -d $(DESTDIR)$(spooldir)/saved + install -d $(DESTDIR)$(spooldir)/store + install -d $(DESTDIR)$(confdir) + install -d $(DESTDIR)$(crondir) + install -d $(DESTDIR)$(rcdir) + + install -m 0755 dlife_soup $(srcdir)/dlife_client.pl \ + $(srcdir)/dlife_server.pl $(DESTDIR)$(bindir) + install -m 0644 $(DOCS) $(DESTDIR)$(docdir) + install -m 0644 god.dlo $(DESTDIR)$(spooldir) + install -m 0644 $(srcdir)/client.conf $(srcdir)/soup.conf \ + $(DESTDIR)$(confdir) + install -m 0644 $(srcdir)/dlife_client.cron $(DESTDIR)$(crondir) + install -m 0644 $(srcdir)/dlife.rc $(DESTDIR)$(rcdir) + + chown -R dlife.dlife $(DESTDIR)$(spooldir) ||: + +define WEBSITE + +XXX PUT YOUR WEBSITE HERE. IF YOU DON\'T WANT TO MANAGE A WEBSITE WITH +XXX MAKE+ THEN JUST DELETE THIS SECTION AND THE upload_website RULE. + +endef + +upload_website: + scp $(PACKAGE)-$(VERSION).tar.gz $(PACKAGE)-$(VERSION)-1.*.rpm \ + $(PACKAGE)-$(VERSION).bin.tar.gz \ + you@yourmachine.example.com:/var/www/html/$(PACKAGE)/files + scp index.html you@yourmachine.example.com:/var/www/html/$(PACKAGE)/ + +.PHONY: build configure test upload_website diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..a30745f --- /dev/null +++ b/Makefile.am @@ -0,0 +1,117 @@ +# DLIFE (C) 2000 Richard W.M. Jones +# and other authors listed in the ``AUTHORS'' file. +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id: Makefile.am,v 1.3 2002/04/05 17:20:11 rich Exp $ + +AUTOMAKE_OPTIONS = foreign + +EXTRA_DIST = .cvsignore \ + Build \ + Build.local \ + dlife_asm.pl \ + dlife_client.pl.in \ + dlife_disasm.pl \ + dlife_server.pl.in \ + dlife.spec \ + dlife.spec.in \ + god.dla \ + index.html.in \ + servers.txt \ + debian/changelog \ + debian/conffiles \ + debian/control \ + debian/copyright \ + debian/cron.d \ + debian/dirs \ + debian/docs \ + debian/files \ + debian/init.d \ + debian/postinst.debhelper \ + debian/postrm.debhelper \ + debian/prerm.debhelper \ + debian/rules \ + debian/substvars \ + $(bin_SCRIPTS) \ + $(conf_DATA) \ + $(cron_DATA) \ + $(doc_DATA) \ + $(rc_SCRIPTS) \ + $(spool_DATA) + +docdir = @DOCDIR@ +doc_DATA = AUTHORS \ + INSTALL \ + README \ + archproc.gif \ + archproc.fig \ + archref.html \ + index.html \ + machineref.html + +spooldir = @SPOOLDIR@ +spool_DATA = god.dlo + +confdir = @CONFDIR@ +conf_DATA = client.conf soup.conf + +if INSTALL_CRON +crondir = @CRONDIR@ +else +crondir = /tmp +endif +cron_DATA = dlife_client.cron + +if INSTALL_RC +rcdir = @RCDIR@ +else +rcdir = /tmp +endif +rc_SCRIPTS = dlife.rc + +bin_PROGRAMS = dlife_soup + +bin_SCRIPTS = dlife_client.pl dlife_server.pl + +dlife_soup_SOURCES = \ + cell.c \ + cell.h \ + crc.c \ + crc.h \ + dlink.h \ + exec.c \ + image.c \ + image.h \ + load.c \ + load.h \ + main.c \ + params.h \ + random.c \ + random.h \ + soup.c \ + soup.h \ + state.c \ + state.h \ + types.h + +install-data-hook: + $(mkinstalldirs) $(DESTDIR)$(spooldir)/incoming + $(mkinstalldirs) $(DESTDIR)$(spooldir)/outgoing + $(mkinstalldirs) $(DESTDIR)$(spooldir)/saved + $(mkinstalldirs) $(DESTDIR)$(spooldir)/store + ifndef NO_CHOWN + chown -R dlife.dlife $(DESTDIR)$(spooldir) + endif diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..7bef584 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,590 @@ +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# DLIFE (C) 2000 Richard W.M. Jones +# and other authors listed in the ``AUTHORS'' file. +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id: Makefile.am,v 1.3 2002/04/05 17:20:11 rich Exp $ + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +CONFDIR = @CONFDIR@ +CRONDIR = @CRONDIR@ +DOCDIR = @DOCDIR@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +RCDIR = @RCDIR@ +RELEASEDATE = @RELEASEDATE@ +SPOOLDIR = @SPOOLDIR@ +VERSION = @VERSION@ + +AUTOMAKE_OPTIONS = foreign + +EXTRA_DIST = .cvsignore Build Build.local dlife_asm.pl dlife_client.pl.in dlife_disasm.pl dlife_server.pl.in dlife.spec dlife.spec.in god.dla index.html.in servers.txt debian/changelog debian/conffiles debian/control debian/copyright debian/cron.d debian/dirs debian/docs debian/files debian/init.d debian/postinst.debhelper debian/postrm.debhelper debian/prerm.debhelper debian/rules debian/substvars $(bin_SCRIPTS) $(conf_DATA) $(cron_DATA) $(doc_DATA) $(rc_SCRIPTS) $(spool_DATA) + + +docdir = @DOCDIR@ +doc_DATA = AUTHORS INSTALL README archproc.gif archproc.fig archref.html index.html machineref.html + + +spooldir = @SPOOLDIR@ +spool_DATA = god.dlo + +confdir = @CONFDIR@ +conf_DATA = client.conf soup.conf +@INSTALL_CRON_TRUE@crondir = @CRONDIR@ +@INSTALL_CRON_FALSE@crondir = /tmp +cron_DATA = dlife_client.cron +@INSTALL_RC_TRUE@rcdir = @RCDIR@ +@INSTALL_RC_FALSE@rcdir = /tmp +rc_SCRIPTS = dlife.rc + +bin_PROGRAMS = dlife_soup + +bin_SCRIPTS = dlife_client.pl dlife_server.pl + +dlife_soup_SOURCES = cell.c cell.h crc.c crc.h dlink.h exec.c image.c image.h load.c load.h main.c params.h random.c random.h soup.c soup.h state.c state.h types.h + +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = dlife_client.pl dlife_server.pl dlife.spec \ +index.html +PROGRAMS = $(bin_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +dlife_soup_OBJECTS = cell.o crc.o exec.o image.o load.o main.o random.o \ +soup.o state.o +dlife_soup_LDADD = $(LDADD) +dlife_soup_DEPENDENCIES = +dlife_soup_LDFLAGS = +SCRIPTS = $(bin_SCRIPTS) $(rc_SCRIPTS) + +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DATA = $(conf_DATA) $(cron_DATA) $(doc_DATA) $(spool_DATA) + +DIST_COMMON = README ./stamp-h.in AUTHORS COPYING INSTALL Makefile.am \ +Makefile.in acconfig.h aclocal.m4 config.h.in configure configure.in \ +dlife.spec.in dlife_client.pl.in dlife_server.pl.in index.html.in \ +install-sh missing mkinstalldirs + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/cell.P .deps/crc.P .deps/exec.P .deps/image.P \ +.deps/load.P .deps/main.P .deps/random.P .deps/soup.P .deps/state.P +SOURCES = $(dlife_soup_SOURCES) +OBJECTS = $(dlife_soup_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): configure.in + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +config.h: stamp-h + @if test ! -f $@; then \ + rm -f stamp-h; \ + $(MAKE) stamp-h; \ + else :; fi +stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=config.h \ + $(SHELL) ./config.status + @echo timestamp > stamp-h 2> /dev/null +$(srcdir)/config.h.in: $(srcdir)/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/stamp-h.in; \ + $(MAKE) $(srcdir)/stamp-h.in; \ + else :; fi +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f config.h + +maintainer-clean-hdr: +dlife_client.pl: $(top_builddir)/config.status dlife_client.pl.in + cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status +dlife_server.pl: $(top_builddir)/config.status dlife_server.pl.in + cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status +dlife.spec: $(top_builddir)/config.status dlife.spec.in + cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status +index.html: $(top_builddir)/config.status index.html.in + cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +mostlyclean-binPROGRAMS: + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +distclean-binPROGRAMS: + +maintainer-clean-binPROGRAMS: + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(bin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +dlife_soup: $(dlife_soup_OBJECTS) $(dlife_soup_DEPENDENCIES) + @rm -f dlife_soup + $(LINK) $(dlife_soup_LDFLAGS) $(dlife_soup_OBJECTS) $(dlife_soup_LDADD) $(LIBS) + +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_SCRIPTS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \ + $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ + else if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \ + $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ + else :; fi; fi; \ + done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + list='$(bin_SCRIPTS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ + done + +install-rcSCRIPTS: $(rc_SCRIPTS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(rcdir) + @list='$(rc_SCRIPTS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(rcdir)/`echo $$p|sed '$(transform)'`"; \ + $(INSTALL_SCRIPT) $$p $(DESTDIR)$(rcdir)/`echo $$p|sed '$(transform)'`; \ + else if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(rcdir)/`echo $$p|sed '$(transform)'`"; \ + $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(rcdir)/`echo $$p|sed '$(transform)'`; \ + else :; fi; fi; \ + done + +uninstall-rcSCRIPTS: + @$(NORMAL_UNINSTALL) + list='$(rc_SCRIPTS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(rcdir)/`echo $$p|sed '$(transform)'`; \ + done + +install-confDATA: $(conf_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(confdir) + @list='$(conf_DATA)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(confdir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(confdir)/$$p; \ + else if test -f $$p; then \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(confdir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(confdir)/$$p; \ + fi; fi; \ + done + +uninstall-confDATA: + @$(NORMAL_UNINSTALL) + list='$(conf_DATA)'; for p in $$list; do \ + rm -f $(DESTDIR)$(confdir)/$$p; \ + done + +install-cronDATA: $(cron_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(crondir) + @list='$(cron_DATA)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(crondir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(crondir)/$$p; \ + else if test -f $$p; then \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(crondir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(crondir)/$$p; \ + fi; fi; \ + done + +uninstall-cronDATA: + @$(NORMAL_UNINSTALL) + list='$(cron_DATA)'; for p in $$list; do \ + rm -f $(DESTDIR)$(crondir)/$$p; \ + done + +install-docDATA: $(doc_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(docdir) + @list='$(doc_DATA)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(docdir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(docdir)/$$p; \ + else if test -f $$p; then \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(docdir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(docdir)/$$p; \ + fi; fi; \ + done + +uninstall-docDATA: + @$(NORMAL_UNINSTALL) + list='$(doc_DATA)'; for p in $$list; do \ + rm -f $(DESTDIR)$(docdir)/$$p; \ + done + +install-spoolDATA: $(spool_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(spooldir) + @list='$(spool_DATA)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(spooldir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(spooldir)/$$p; \ + else if test -f $$p; then \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(spooldir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(spooldir)/$$p; \ + fi; fi; \ + done + +uninstall-spoolDATA: + @$(NORMAL_UNINSTALL) + list='$(spool_DATA)'; for p in $$list; do \ + rm -f $(DESTDIR)$(spooldir)/$$p; \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP)) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign Makefile + $(mkinstalldirs) $(distdir)/debian + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +all-recursive-am: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +install-exec-am: install-binPROGRAMS install-binSCRIPTS +install-exec: install-exec-am + +install-data-am: install-rcSCRIPTS install-confDATA install-cronDATA \ + install-docDATA install-spoolDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ + uninstall-rcSCRIPTS uninstall-confDATA \ + uninstall-cronDATA uninstall-docDATA \ + uninstall-spoolDATA +uninstall: uninstall-am +all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(DATA) config.h +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(bindir) \ + $(DESTDIR)$(rcdir) $(DESTDIR)$(confdir) \ + $(DESTDIR)$(crondir) $(DESTDIR)$(docdir) \ + $(DESTDIR)$(spooldir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-hdr mostlyclean-binPROGRAMS \ + mostlyclean-compile mostlyclean-tags mostlyclean-depend \ + mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-hdr clean-binPROGRAMS clean-compile clean-tags \ + clean-depend clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-hdr distclean-binPROGRAMS distclean-compile \ + distclean-tags distclean-depend distclean-generic \ + clean-am + +distclean: distclean-am + -rm -f config.status + +maintainer-clean-am: maintainer-clean-hdr maintainer-clean-binPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-depend maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ +maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile uninstall-binSCRIPTS install-binSCRIPTS \ +uninstall-rcSCRIPTS install-rcSCRIPTS uninstall-confDATA \ +install-confDATA uninstall-cronDATA install-cronDATA uninstall-docDATA \ +install-docDATA uninstall-spoolDATA install-spoolDATA tags \ +mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \ +distdir mostlyclean-depend distclean-depend clean-depend \ +maintainer-clean-depend info-am info dvi-am dvi check check-am \ +installcheck-am installcheck all-recursive-am install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +install-data-hook: + $(mkinstalldirs) $(DESTDIR)$(spooldir)/incoming + $(mkinstalldirs) $(DESTDIR)$(spooldir)/outgoing + $(mkinstalldirs) $(DESTDIR)$(spooldir)/saved + $(mkinstalldirs) $(DESTDIR)$(spooldir)/store + ifndef NO_CHOWN + chown -R dlife.dlife $(DESTDIR)$(spooldir) + endif + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/README b/README new file mode 100644 index 0000000..c43cf96 --- /dev/null +++ b/README @@ -0,0 +1,22 @@ +Distributed Artificial Life (DLIFE) +----------------------------------- +By Richard W.M. Jones + +What is DLIFE? +-------------- + +DLIFE is a distributed version of Tom S. Ray's Tierra artificial life +program. Note that the machine language used is similar to but not +compatible with Tierra. Tom Ray talks about his work (as far as I +know, never completed) to create a ``Digital Reserve''. The DLIFE +project is a development of this. + +In other words, it's an alternative to the tedious process of cracking +RC5 keys or searching for aliens. You've got a supercomputer on your +desk, let's go and create some life ... + +It consists of a highly optimized engine for running the artificial +life cells in a virtual machine, written in C, and some Perl scripts +which can upload and download cells from central ``cell-bank'' +servers. + diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 0000000..b0193eb --- /dev/null +++ b/acconfig.h @@ -0,0 +1,16 @@ +#ifndef DLIFE_CONFIG_H +#define DLIFE_CONFIG_H +@TOP@ + +/* + * Defaults for configuration settings + */ + +#undef PACKAGE +#undef VERSION +#undef SPOOLDIR +#undef CONFDIR + +@BOTTOM@ + +#endif /* DLIFE_CONFIG_H */ diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..2361d00 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,170 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4-p6 + +dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# Copyright 2002 Free Software Foundation, Inc. + +# 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, 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., 59 Temple Place - Suite 330, Boston, MA + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.4"]) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION so it can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], + [AM_AUTOMAKE_VERSION([1.4-p6])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN([AM_MISSING_PROG], +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + +AC_DEFUN([AM_CONFIG_HEADER], +[AC_PREREQ([2.12]) +AC_CONFIG_HEADER([$1]) +dnl When config.status generates a header, we must update the stamp-h file. +dnl This file resides in the same directory as the config header +dnl that is generated. We must strip everything past the first ":", +dnl and everything past the last "/". +AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl +ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, +<>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, +<>; do + case " <<$>>CONFIG_HEADERS " in + *" <<$>>am_file "*<<)>> + echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx + ;; + esac + am_indx=`expr "<<$>>am_indx" + 1` +done<<>>dnl>>) +changequote([,]))]) + +# Define a conditional. + +AC_DEFUN([AM_CONDITIONAL], +[AC_SUBST($1_TRUE) +AC_SUBST($1_FALSE) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + diff --git a/archproc.fig b/archproc.fig new file mode 100644 index 0000000..eb6819a --- /dev/null +++ b/archproc.fig @@ -0,0 +1,152 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 2100 825 2775 2025 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2100 825 2775 825 2775 2025 2100 2025 2100 825 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2100 975 2550 975 2550 2025 2100 2025 2100 975 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2550 1200 2775 1200 2775 1275 2550 1275 2550 1200 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2550 1275 2775 1275 2775 1350 2550 1350 2550 1275 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2550 1350 2775 1350 2775 1425 2550 1425 2550 1350 +-6 +6 5850 825 6525 2025 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5850 825 6525 825 6525 2025 5850 2025 5850 825 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5850 975 6300 975 6300 2025 5850 2025 5850 975 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 1200 6525 1200 6525 1275 6300 1275 6300 1200 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 1275 6525 1275 6525 1350 6300 1350 6300 1275 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 1350 6525 1350 6525 1425 6300 1425 6300 1350 +-6 +6 675 5400 1650 6330 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 808 5400 1517 5400 1517 6020 808 6020 808 5400 +2 4 0 1 0 7 50 0 -1 0.000 0 0 4 0 0 5 + 1473 5931 1473 5489 852 5489 852 5931 1473 5931 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 808 6109 1517 6109 1650 6330 675 6330 808 6109 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 853 6135 1337 6135 1428 6286 762 6286 853 6135 +-6 +6 1950 6450 2925 7380 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2083 6450 2792 6450 2792 7070 2083 7070 2083 6450 +2 4 0 1 0 7 50 0 -1 0.000 0 0 4 0 0 5 + 2748 6981 2748 6539 2127 6539 2127 6981 2748 6981 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2083 7159 2792 7159 2925 7380 1950 7380 2083 7159 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2128 7185 2612 7185 2703 7336 2037 7336 2128 7185 +-6 +6 3525 5775 4500 6705 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3658 5775 4367 5775 4367 6395 3658 6395 3658 5775 +2 4 0 1 0 7 50 0 -1 0.000 0 0 4 0 0 5 + 4323 6306 4323 5864 3702 5864 3702 6306 4323 6306 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3658 6484 4367 6484 4500 6705 3525 6705 3658 6484 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3703 6510 4187 6510 4278 6661 3612 6661 3703 6510 +-6 +6 3525 5175 4500 5456 +1 4 0 1 0 7 50 0 -1 0.000 1 0.0000 3666 5326 39 39 3633 5305 3698 5348 +1 4 0 1 0 7 50 0 -1 0.000 1 0.0000 3774 5326 39 39 3742 5305 3807 5348 +1 4 0 1 0 7 50 0 -1 0.000 1 0.0000 3882 5326 39 39 3850 5305 3915 5348 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3525 5175 4500 5175 4500 5456 3525 5456 3525 5175 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4110 5326 4153 5326 4153 5456 4110 5456 4110 5326 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4197 5326 4240 5326 4240 5456 4197 5456 4197 5326 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4283 5326 4327 5326 4327 5456 4283 5456 4283 5326 +-6 +6 5100 6075 6075 7005 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5233 6075 5942 6075 5942 6695 5233 6695 5233 6075 +2 4 0 1 0 7 50 0 -1 0.000 0 0 4 0 0 5 + 5898 6606 5898 6164 5277 6164 5277 6606 5898 6606 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5233 6784 5942 6784 6075 7005 5100 7005 5233 6784 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5278 6810 5762 6810 5853 6961 5187 6961 5278 6810 +-6 +6 900 4725 2100 5175 +4 0 0 50 0 0 12 0.0000 4 180 1170 900 4875 (runs from cron\001 +4 0 0 50 0 0 12 0.0000 4 180 870 900 5100 every hour)\001 +-6 +6 1875 5775 3075 6225 +4 0 0 50 0 0 12 0.0000 4 180 1170 1875 5925 (runs from cron\001 +4 0 0 50 0 0 12 0.0000 4 180 870 1875 6150 every hour)\001 +-6 +6 5025 5475 6225 5925 +4 0 0 50 0 0 12 0.0000 4 180 1170 5025 5625 (runs from cron\001 +4 0 0 50 0 0 12 0.0000 4 180 870 5025 5850 every hour)\001 +-6 +6 6825 4800 8025 5250 +4 0 0 50 0 0 12 0.0000 4 180 1170 6825 4950 (runs from cron\001 +4 0 0 50 0 0 12 0.0000 4 180 870 6825 5175 every hour)\001 +-6 +6 6975 5370 7950 6300 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7108 5370 7817 5370 7817 5990 7108 5990 7108 5370 +2 4 0 1 0 7 50 0 -1 0.000 0 0 4 0 0 5 + 7773 5901 7773 5459 7152 5459 7152 5901 7773 5901 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7108 6079 7817 6079 7950 6300 6975 6300 7108 6079 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7153 6105 7637 6105 7728 6256 7062 6256 7153 6105 +-6 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 2475 5325 2475 2550 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 3600 4200 2850 2475 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 4425 4125 5700 2475 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 5700 5100 6075 2550 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 7275 4425 6450 2475 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 1425 4275 2100 2475 +4 0 0 50 0 0 12 0.0000 4 180 1080 2025 2400 dlife_server.pl\001 +4 0 0 50 0 0 12 0.0000 4 180 1080 5625 2325 dlife_server.pl\001 +4 0 0 50 0 0 12 0.0000 4 180 1020 900 4500 dlife_client.pl\001 +4 0 0 50 0 0 12 0.0000 4 180 1020 2025 5625 dlife_client.pl\001 +4 0 0 50 0 0 12 0.0000 4 180 1020 3525 4425 dlife_client.pl\001 +4 0 0 50 0 0 12 0.0000 4 180 1020 5100 5325 dlife_client.pl\001 +4 0 0 50 0 0 12 0.0000 4 180 1020 6900 4650 dlife_client.pl\001 +4 0 0 50 0 0 12 0.0000 4 180 795 3375 4725 (runs from\001 +4 0 0 50 0 0 12 0.0000 4 180 1545 3375 4950 /etc/ppp/ip-up.local)\001 +4 0 0 50 0 0 12 0.0000 4 135 540 3675 5700 modem\001 +4 0 0 50 0 0 12 0.0000 4 180 780 675 6750 dlife_soup\001 +4 0 0 50 0 0 12 0.0000 4 180 780 2025 7650 dlife_soup\001 +4 0 0 50 0 0 12 0.0000 4 180 780 2025 7875 dlife_soup\001 +4 0 0 50 0 0 12 0.0000 4 180 780 3600 7050 dlife_soup\001 +4 0 0 50 0 0 12 0.0000 4 180 780 5250 7350 dlife_soup\001 +4 0 0 50 0 0 12 0.0000 4 180 780 7125 6675 dlife_soup\001 diff --git a/archproc.gif b/archproc.gif new file mode 100644 index 0000000..7c5eabc Binary files /dev/null and b/archproc.gif differ diff --git a/archref.html b/archref.html new file mode 100644 index 0000000..5e5c20b --- /dev/null +++ b/archref.html @@ -0,0 +1,489 @@ + + + + DLIFE distributed architecture reference + + + +

DLIFE distributed architecture reference

+ +

+ DLIFE is distributed, meaning that many people + may allocate their spare computing cycles and + memory in order to form something which approximates + a very large single soup. Actually modelling a + very large soup, however, would be very difficult: + such a program would have a high communication + overhead, would be totally unsuitable to run on + the Internet, and adding nodes to this would bring + diminishing returns. Therefore DLIFE uses a simpler + model: individual computers run small soups, and + from time to time, soups exchange a few cells at + random with each other. In effect we form a series + of islands connected by archipelagoes. +

+ +

Processes

+ +

+ There are currently three processes involved: +

+ +
    +
  • dlife_soup: This program runs continuously, + one on each client CPU, simulating a single soup. + It is written in C and designed to be as small and + fast as possible. This is the only part of DLIFE which + clients need to run all the time. +
  • dlife_client.pl: This is a Perl script which + runs infrequently (normally once per hour, but it + could be more or less often, or it could be run + on-demand when a PPP connection is brought up). The Perl script is + responsible for exchanging cells with the DLIFE server. +
  • dlife_server.pl: This is the DLIFE server + script. It only runs on servers (obviously). It acts + as a repository for cells being exchanged between + clients. +
+ +

+ The following diagram shows the interaction between these + three programs. +

+ + [Diagram] Interaction between DLIFE processes + +

+ As shown, there are five client computers and two + servers. The second client computer has two CPUs, + and runs dlife_soup continuously on both. The + third client computer is connected to the Internet + by a modem, and so runs dlife_client.pl from + /etc/ppp/ip-up.local (this script runs whenever + the Internet connection is brought up). All the + other computers are permanently connected to the + Internet, and dlife_client.pl runs periodically + from cron. Clients may connect and exchange + cells with more than one server. In the diagram + above, the third client computer connects to + both servers. +

+ +

Cells in files

+ +

+ The long-running dlife_soup program does not + contain any network code. All network communications + are handled by dlife_client.pl. Instead, dlife_soup + contains code to save and load cells to files. +

+ +

+ dlife_soup saves (by default) six cells per hour, + at random, into the directory: +

+ +

+ /var/spool/dlife/outgoing/ +

+ +

+ dlife_soup loads (by default) four cells per hour, + at random, from the directory: +

+ +

+ /var/spool/dlife/incoming/ +

+ +

+ The dlife_client.pl program takes some cells at + random from the outgoing spool + directory and uploads them to one or more servers + (see the configuration section + below). It then asks the server(s) to send some + cells, and it saves these in the incoming + spool directory. +

+ +

+ The dlife_server.pl program listens for client + connections, and uploads or downloads cells. It + saves its cells in the directory: +

+ +

+ /var/spool/dlife/store/ +

+ +

DLIFE network protocol

+ +

+ The DLIFE network protocol is a very simple + ASCII based protocol, similar to (but much + more limited than) FTP. +

+ +

+ Servers listen for connections on port 5904. + When a client connects, they send back the following + identifying string: +

+ +
+DLIFE SERVER <version> <protocol> <CR> <LF>
+
+ +

+ <version> is the server version, for + information only. +

+ +

+ <protocol> is the protocol version. The + protocol described below is version 1.x (for some digit + ``x''). If a server reports a different major version + number (eg. 2.x) then this is an indication that the + protocol has changed dramatically and current clients + should give up and abort. +

+ +

+ Clients connect to servers on port 5904 and + issue a series of simple four letter commands. + Each command should take the form: +

+ +
+<command> [ <space> <arguments ...> ] <CR> <LF>
+
+ +

+ There are currently four commands: HELO, + STOR, RETR and QUIT. +

+ +

+ Servers respond to commands with a three digit + response code and some optional human-readable text: +

+ +
+XYZ [ <space> text ... ] <CR> <LF>
+
+ +

+ Of the response code, only the first digit (``X'') + is meaningful to clients. As for FTP, this digit can + have the following meanings: +

+ + + + + + + + + + + + + + + + + + + + + +
Response code Meaning
1xx Command OK. Ready to send data, or ready + to receive data. +
2xx Command OK. Ready for your next command. +
4xx Temporary error. The client can retry the last command + without modification and it may well succeed next time. +
5xx Error. The client should not just retry the same + command, but needs to reformulate the command or + cancel the operation and report an error back to the + user. +
+ +

The HELO command

+ +

+ The HELO command has the following form: +

+ +
+HELO <space> <client_hostname>
+          <space> <client_version> <CR> <LF>
+
+ +

+ where <client_hostname> is the client + hostname (or the client may just send "-" character) + and <client_version> is the client version + number, used just for information only. +

+ +

+ The server should always respond with 2xx to + this command. +

+ +

+ A typical interaction: +

+ +
+> HELO - 0.0.12
+< 200 Hello.
+
+ +

The STOR command

+ +

+ The STOR command is used to upload a single + cell to the server. +

+ +

+ The format of the command is: +

+ +
+STOR <CR> <LF>
+
+ +

+ If the server accepts the command and is ready to + upload a cell, it will reply with a 1xx response. + The client should then send the cell as a series + of hex nybbles, terminated by the sequence + <CR> <LF> . <CR> <LF>. +

+ +

+ A typical interaction: +

+ +
+> STOR
+< 100 Send me the cell, terminated by ".".
+> 00000000010901010100002227
+> 0000000100FFFFFFFFFFFFFFFF
+>      :      :
+>      :      :
+> 00010000002402020202020202022027
+> 0001010101
+> .
+< 200 Cell was uploaded OK.
+
+ +

+ Servers will typically have limitations on the + number and type of cells that they will accept. + Generally they will only accept a small number + of uploads per session, and each cell will be + limited to 8192 bytes or less. +

+ +

The RETR command

+ +

+ The RETR command is used to download + a cell from the cell bank. The format of the command + is: +

+ +
+RETR <CR> <LF>
+
+ +

+ If the server is ready to serve a cell, it will + reply with a 1xx response, followed by a series + of hex nybbles and terminated by the + sequence + <CR> <LF> . <CR> <LF> + and immediately followed by a 2xx response. +

+ +

+ A typical interaction: +

+ +
+> RETR
+< 100 OK. Sending you a cell.
+< 00000000010901010100002227
+< 0000000100FFFFFFFFFFFFFFFF
+<      :      :
+<      :      :
+< 00010000002402020202020202022027
+< 0001010101
+< .
+< 200 Cell was sent OK.
+
+ +

The QUIT command

+ +

+ The QUIT command terminates a session + (clients may also just close a session). +

+ +

+ The format of the command is: +

+ +
+QUIT <CR> <LF>
+
+ +

+ The server responds with a 2xx message and then + closes its end of the connection. +

+ +

+ A typical interaction: +

+ +
+> QUIT
+< 200 Goodbye.
+(socket is closed)
+
+ +

Configuration files

+ +

/etc/dlife/client.conf

+ +

+ This file is used to configure the network client. + The file tells the client which server or servers + to connect to. +

+ +

+ The client can be configured to: +

+ +
    +
  • Download a list of servers from a web page. +
  • Contact only servers in the current ``zone'' (eg. + only servers in the UK or Europe). And/or: +
  • Contact servers directly by name. +
+ +

server_url command

+ +

+ The server_url command may be optionally + given. It directs the client to download the web + page given in the URL. The web page should contain + a master list of servers. +

+ +
+server_url http://dlife.annexia.org/servers.txt
+
+ +

server_zone command

+ +

+ The server_zone command is optional. It + should be used in conjunction with the + server_url command. It + directs the client to only consider servers + in the particular zone or zones listed. +

+ +

+ The general form is: +

+ +
+server_zone <zone> [<zone> [...]]
+
+ +

+ Each <zone> argument should have the + form: +

+ +
    +
  • An ISO3166 country code, eg. uk, us. Or: +
  • A geographical continent, eg. eu. Or: +
  • A domain name, preceeded by a dot ("."), + eg. .bibliotech.net. +
+ +

server command

+ +

+ The server command directs the client to + connect directly the server or servers listed. +

+ +
+server dlife1.bibliotech.co.uk dlife2.bibliotech.co.uk
+
+ +

max_cells_upload_per_pass command

+ +

+ The max_cells_upload_per_pass directs + the client to attempt to upload this many cells + in a pass. Note that the server probably imposes + its own limit. +

+ +

max_cells_download_per_pass command

+ +

+ The max_cells_download_per_pass directs + the client to attempt to download this many cells + in a pass. Note that the server probably imposes + its own limit. It is a good idea to ensure that + max_cells_upload_per_pass > + max_cells_download_per_pass. +

+ +

/etc/dlife/soup.conf

+ +

+ The soup.conf file configures various + internal aspects of the DLIFE virtual machine. + For full documentation, please see the example + file provided with the source distribution. +

+ +

Typical configurations

+ +

Default configuration

+ + + + + + + + + + +
+
Richard Jones
+ + +Last modified: Wed Oct 11 23:19:19 BST 2000 + + + diff --git a/cell.c b/cell.c new file mode 100644 index 0000000..c7f1f1a --- /dev/null +++ b/cell.c @@ -0,0 +1,703 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: cell.c,v 1.3 2002/12/11 17:16:21 rich Exp $ + */ + +#include "config.h" + +#include +#include + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_ASSERT_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SIGNAL_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_DIRENT_H +#include +#endif + +#ifdef HAVE_SYSLOG_H +#include +#endif + +#include "cell.h" +#include "soup.h" +#include "random.h" +#include "params.h" +#include "dlink.h" +#include "image.h" +#include "load.h" + +#define PRINT_SIMULATION_STATS 0 + +static volatile int quit = 0, save = 0, outgoing = 0, incoming = 0, info = 0; +static void save_cell_in_outgoing (struct state *, const struct cell *); + +/* Initialize the common fields of a cell. */ +static inline void +init_cell (struct cell *cell) +{ + /* Public fields are subject to initialization errors. */ + if (! chance (cell_initialization_failure)) + { + cell->a = cell->b = cell->i = cell->p = 0; + memset (cell->stack, 0, sizeof cell->stack); + } + else + { + int i; + + cell->a = get_rand_short (); + cell->b = get_rand_short (); + cell->i = get_rand_short (); + cell->p = 0; /* Cell would be non-viable otherwise. */ + + for (i = 0; i < STACK_SIZE; ++i) + cell->stack[i] = get_rand_short (); + } + cell->next = cell->prev = 0; + cell->worse = cell->better = 0; + cell->sp = 0; + cell->errors = 0; + cell->state = state_exec; + cell->dir = 0; + cell->plen = 0; + cell->lim = 0; + cell->frag = 0; + cell->daughter = 0; + cell->cycle = 0; + cell->crc = 0; /* Initialize these at DIVIDE. */ + cell->mother_crc = 0; +} + +struct cell * +cell_malloc (struct state *state, + const struct cell *mother, + struct soup_frag *daughter_frag) +{ + struct cell *cell; + + cell = malloc (sizeof (struct cell)); + if (cell == 0) { perror ("malloc"); abort (); } + + init_cell (cell); + cell->frag = daughter_frag; + + state->nr_cells_allocated++; + + return cell; +} + +void +cell_divide (struct state *state, + const struct cell *mother, + struct cell *daughter) +{ + /* Initialize CRC fields. */ + daughter->mother_crc = mother->crc; + daughter->crc = soup_frag_compute_crc32 (state, daughter->frag); + + /* If the outgoing signal has just gone, then this cell is the + * lucky cell which has been nominated to be written into the + * outgoing queue. + */ + if (outgoing) + { + outgoing = 0; + save_cell_in_outgoing (state, daughter); + } + +#if 0 + printf ("DIVIDE: 0x%08X/%d -> 0x%08X/%d\n", + daughter->mother_crc, mother->frag->len, + daughter->crc, daughter->frag->len); +#endif +} + +/* Put a cell onto the alive list. */ +void +cell_activate (struct state *state, struct cell *cell) +{ + insert_before_first (cell, &state->alive_list); + + /* We assume that cells start off with no errors. */ + assert (cell->errors == 0); + insert_before_first (cell, &state->best_list); + + state->nr_cells_alive++; +} + +/* This function is called after the INC_ERRORS macro has incremented + * the number of errors in a cell and found that the cell should be + * moved up in the linked list by one or more places. + */ +void +_cell_move_worse (struct state *state, struct cell *cell) +{ + while (cell->worse && cell->errors > cell->worse->errors) + move_towards_last (cell, &state->best_list); +} + +/* Kill a cell (and undivided offspring, if any). */ +void +cell_kill (struct state *state, struct cell *cell) +{ + remove_element (cell, &state->alive_list); + remove_element (cell, &state->best_list); + + soup_frag_free (state, cell->frag); + + /* Pro-life programmers may wish to look away at this point ... */ + if (cell->daughter) + { + soup_frag_free (state, cell->daughter->frag); + cell->daughter->errors = -1; + free (cell->daughter); + + state->nr_cells_allocated--; + } + + cell->errors = -1; + free (cell); + + state->nr_cells_allocated--; + state->nr_cells_alive--; +} + +/* Run the grim reaper, culling cells until the amount of free soup + * left is less than the appropriate threshold. + */ +static inline void +reaper (struct state *state) +{ + int bytes_to_free; + + /* How many bytes do we need to free up? */ + bytes_to_free = (100 - reaper_reap_threshold) * state->soup_size + / 100 - state->soup_free; + assert (bytes_to_free > 0); + +#if 0 + printf ("\ninvoking reaper to save %d bytes of soup ...\n", bytes_to_free); +#endif + + while (bytes_to_free > 0) + { + struct cell *cell; + + /* Pick the most error-prone cell and kill it. */ + cell = (struct cell *) state->best_list.last; + bytes_to_free -= cell->frag->len; + if (cell->daughter) bytes_to_free -= cell->daughter->frag->len; + +#if 0 + printf (" killing cell with %d errors\n", cell->errors); +#endif + + cell_kill (state, cell); + } +} + +/* Remove any cells with more than MAX_ERRORS errors. */ +static inline void +reap_error_prone_cells (struct state *state) +{ + struct cell *cell; + + /* Just go down the list of cells, killing them until we + * reach a cell with < MAX_ERRORS errors. + */ + while ((cell = (struct cell *) state->best_list.last) && + cell->errors >= MAX_ERRORS) + { +#if 0 + printf ("killing cell with %d errors (>= MAX_ERRORS)\n", cell->errors); +#endif + + cell_kill (state, cell); + } +} + +static void +check_one_cell (struct state *state, const struct cell *cell, int is_daughter) +{ + assert (cell->sp >= 0 && cell->sp < STACK_SIZE); + assert (cell->errors >= 0); + assert (cell->state == state_exec || cell->state == state_find); + assert (cell->dir >= -1 && cell->dir <= 1); + assert (cell->frag != 0); + + if (cell->daughter) + { + assert (is_daughter == 0); + check_one_cell (state, cell->daughter, 1); + } +} + +/* Check the consistency of each cell. This is only used when we are + * debugging the simulation. + */ +void +cell_check (struct state *state) +{ + const struct cell *p; + int alive = 0, allocated = 0, errors = 0; + + /* Check the alive list and each cell on it. */ + for (p = (struct cell *) state->alive_list.first; p; p = p->next) + { + check_one_cell (state, p, 0); + alive++; allocated++; + if (p->daughter) allocated++; + } + + assert (alive == state->nr_cells_alive); + assert (allocated == state->nr_cells_allocated); + + /* Check the best list. */ + alive = allocated = 0; + for (p = (struct cell *) state->best_list.first; p; p = p->worse) + { + assert (errors <= p->errors); + errors = p->errors; + alive++; allocated++; + if (p->daughter) allocated++; + } + + assert (alive == state->nr_cells_alive); + assert (allocated == state->nr_cells_allocated); +} + +/* Take a complete checkpoint of the state and save it onto disk. */ +static void +save_me (struct state *state) +{ + char filename2[256], filename3[256]; + + sprintf (filename2, "%s.new", state->filename); + + if (image_save (state, filename2) == 0) + { + sprintf (filename3, "%s~", state->filename); + + rename (state->filename, filename3); + rename (filename2, state->filename); + + if (verbose) + printf ("CPU %d: Saved soup image to file.\n", state->thread_num); + } + else + { + sprintf (filename3, "/tmp/%s", state->filename); + + if (image_save (state, filename3) == 0) + { + fprintf (stderr, + "save directory is unwritable! saved to %s instead\n", + filename3); + } + else + { + fprintf (stderr, "could not save state!\n"); + } + } +} + +/* Check the incoming queue. */ +static void +check_incoming (struct state *state) +{ + DIR *dir; + struct dirent *d; + char filename[256]; + int cells_read = 0; + +#ifndef HAVE_OPENDIR +#error "require working opendir/readdir/closedir" +#endif + + dir = opendir ("incoming"); + if (dir == NULL) { perror ("incoming"); return; } + + while ((d = readdir (dir)) != 0) + { + int len = strlen (d->d_name); + + if (len >= 4 && + d->d_name[len-4] == '.' && + d->d_name[len-3] == 'd' && + d->d_name[len-2] == 'l' && + d->d_name[len-1] == 'o') + { + if (cells_read < max_cells_incoming_per_pass) + { + struct cell *cell; + + sprintf (filename, "incoming/%s", d->d_name); + + /* Read the contents of the file. */ + cell = load_cell (state, filename); + + if (cell) + { + cell_activate (state, cell); + cells_read++; + } + } + + /* Remove the file - we've finished with it now. */ + unlink (filename); + } + } +} + +static void +info_to_syslog (const struct state *state) +{ + int soup_used_percent + = 100 * (state->soup_size - state->soup_free) / state->soup_size; + +#ifdef HAVE_SYSLOG + syslog (LOG_INFO, + "#%d: cycles: %LuB cells: %d [+%d] soup: %d%% (%d/%d)", + state->thread_num, + state->cell_cycle / 1000000000, + state->nr_cells_alive, + state->nr_cells_allocated - state->nr_cells_alive, + soup_used_percent, + state->soup_size - state->soup_free, + state->soup_size); +#endif +} + +static void +catch_quit (int sig) +{ + quit = 1; +} + +static void +catch_alarm (int sig) +{ + static int minutes = 0; + + minutes++; + + if ((minutes % save_period) == 0) + { + save = 1; + } + + if ((minutes % outgoing_period) == 0) + { + outgoing = 1; + } + + if ((minutes % incoming_period) == 0) + { + incoming = 1; + } + + if ((minutes % info_period) == 0) + { + info = 1; + } + + alarm (60); +} + +void +run_thread (struct state *state) +{ + int start_time = time (NULL), end_time; + unsigned long long start_cycle = state->cell_cycle; + struct sigaction sigact; + + /* Set up signal handlers to save the soup periodically and + * handle exits gracefully. + */ + memset (&sigact, 0, sizeof sigact); + sigact.sa_handler = catch_quit; + sigact.sa_flags = 0; + + sigaction (SIGINT, &sigact, 0); + sigaction (SIGQUIT, &sigact, 0); + sigaction (SIGTERM, &sigact, 0); + + sigact.sa_handler = catch_alarm; + sigact.sa_flags = SA_RESTART; + sigaction (SIGALRM, &sigact, 0); + + alarm (60); + + while (!quit) + { + struct cell *p; + int soup_used_percent; + + /* Iterate over the list of alive cells, executing a single + * intruction of each. + */ + for (p = (struct cell *) state->alive_list.first; p; p = p->next) + { + exec_insn (state, p); + } + + /* Print some statistics. */ + soup_used_percent + = 100 * (state->soup_size - state->soup_free) / state->soup_size; + +#if PRINT_SIMULATION_STATS + printf ("cycles: %LuB cells: %d [+%d] soup: %d%% \r", + state->cell_cycle / 1000000000, + state->nr_cells_alive, + state->nr_cells_allocated - state->nr_cells_alive, + soup_used_percent); + fflush (stdout); +#endif + + /* Do we need to invoke the grim reaper? */ + if (soup_used_percent >= reaper_invoke_threshold) + { + reaper (state); + } + + /* Do we need to reap any remaining cells with more than + * MAX_ERRORS errors? + */ + reap_error_prone_cells (state); + +#if CHECK + soup_check (state); + cell_check (state); +#endif + + /* Save image every so often. */ + if (save) + { + save = 0; + save_me (state); + } + + /* Check incoming queue? */ + if (incoming) + { + incoming = 0; + check_incoming (state); + } + + /* Dump status information to syslog? */ + if (info) + { + info = 0; + info_to_syslog (state); + } + } + + end_time = time (NULL); + + syslog (LOG_INFO, "CPU %d: Cycles processed: %LuB Time: %dH Cycles/second: %d\n", + state->thread_num, + (state->cell_cycle - start_cycle) / 1000000000, + (end_time - start_time) / (60 * 60), + (int) ((state->cell_cycle - start_cycle) + / (end_time - start_time))); + + /* Each thread is responsible for saving its own state. */ + save_me (state); +} + +/* Something of a hack: get any fragment and return it. */ +struct soup_frag * +_cell_get_any_frag (struct state *state) +{ + return ((struct cell *) state->alive_list.first)->frag; +} + +/* Save the current state of the cell table to a file. This function + * is non-destructive. + */ +void +cell_state_save (struct state *state, FILE *fp) +{ + struct cell *p; + + /* Write out the number of cells. */ + fwrite (&state->nr_cells_allocated, sizeof state->nr_cells_allocated, 1, fp); + fwrite (&state->nr_cells_alive, sizeof state->nr_cells_alive, 1, fp); + + /* Write the cells out in order to the file. */ + for (p = (struct cell *) state->alive_list.first; p; p = p->next) + { + p->fbase = p->frag->base; + fwrite (p, sizeof (struct cell), 1, fp); + if (p->daughter) + { + p->daughter->fbase = p->daughter->frag->base; + fwrite (p->daughter, sizeof (struct cell), 1, fp); + } + } +} + +static int +compare_nr_errors (const void *cv1, const void *cv2) +{ + const struct cell **cp1 = (const struct cell **) cv1; + const struct cell **cp2 = (const struct cell **) cv2; + + return (*cp1)->errors - (*cp2)->errors; +} + +/* Load the cells from a previously saved file. */ +void +cell_state_load (struct state *state, FILE *fp) +{ + int i; + struct cell *p; + struct cell **cellptr_list; + + assert (state->nr_cells_allocated == 0); + assert (state->nr_cells_alive == 0); + + /* Read in the number of cells. */ + if (fread (&state->nr_cells_allocated, + sizeof state->nr_cells_allocated, 1, fp) != 1) + { + syslog (LOG_ERR, "error in cell state\n"); + abort (); + } + if (fread (&state->nr_cells_alive, + sizeof state->nr_cells_alive, 1, fp) != 1) + { + syslog (LOG_ERR, "error in cell state\n"); + abort (); + } + + assert (state->nr_cells_alive <= state->nr_cells_allocated); + + cellptr_list = malloc (sizeof (struct cell *) * state->nr_cells_alive); + + /* Read each cell in from the file. */ + for (i = 0; i < state->nr_cells_alive; ++i) + { + p = malloc (sizeof (struct cell)); + if (p == 0) { perror ("malloc"); abort (); } + + if (fread (p, sizeof (struct cell), 1, fp) != 1) + { + syslog (LOG_ERR, "error in cell state\n"); + abort (); + } + + cellptr_list[i] = p; + + insert_before_last (p, &state->alive_list); + + if (p->daughter) + { + p->daughter = malloc (sizeof (struct cell)); + if (p->daughter == 0) { perror ("malloc"); abort (); } + + if (fread (p->daughter, sizeof (struct cell), 1, fp) != 1) + { + syslog (LOG_ERR, "error in cell state\n"); + abort (); + } + } + } + + /* Order the living cells from best to worst, and from this + * reconstruct the best list. + */ + qsort (cellptr_list, state->nr_cells_alive, sizeof (struct cell *), + compare_nr_errors); + + for (i = 0; i < state->nr_cells_alive; ++i) + { + insert_before_last (cellptr_list[i], &state->best_list); + } +} + +/* This function is used when loading the soup (just after loading the + * cells) to fix up references from the cells to soup fragments. It + * uses the hidden ``fbase'' member of struct cell to save the reference. + */ +void +_cell_fixup_soup_ref (struct state *state, + addr_t fbase, struct soup_frag *frag) +{ + struct cell *p; + + for (p = (struct cell *) state->alive_list.first; p; p = p->next) + { + if (p->fbase == fbase) + { + p->frag = frag; + return; + } + else if (p->daughter && p->daughter->fbase == fbase) + { + p->daughter->frag = frag; + return; + } + } + + syslog (LOG_ERR, "cell fixup not found (fbase = %d)\n", fbase); + abort (); +} + +/* Save a single cell in the outgoing queue. */ +static void +save_cell_in_outgoing (struct state *state, + const struct cell *cell) +{ + char filename[256]; + FILE *fp; + int i; + + /* Choose a random name. */ + sprintf (filename, "outgoing/%d.dlo", get_rand_int()); + + fp = fopen (filename, "w"); + if (fp == NULL) { perror (filename); return; } /* Fail silently. */ + + for (i = 0; i < cell->frag->len; ++i) + fprintf (fp, "%02X", get_soup (state, cell->frag, i)); + + fclose (fp); +} diff --git a/cell.h b/cell.h new file mode 100644 index 0000000..847fcf5 --- /dev/null +++ b/cell.h @@ -0,0 +1,122 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: cell.h,v 1.1 2002/04/05 14:40:25 rich Exp $ + */ + +#ifndef cell_h +#define cell_h + +#include "config.h" + +#include + +#ifdef HAVE_SYS_PARAM_H +#include /* For MAXHOSTNAMELEN. */ +#endif + +#include "types.h" +#include "dlink.h" +#include "state.h" +#include "crc.h" + +struct soup_frag; + +#define STACK_SIZE 16 + +/* These two parameters define the maximum cell size. The first parameter + * is the maximum length of searches permitted by the FINDB/FINDF + * commands. It stops those commands from running wild if a label is + * missing. The second one limits the maximum cell size that may be + * allocated by MALLOC - and hence directly the maximum cell size + * overall. There is also a minimum cell size, although we keep this + * small. + */ +#define FIND_LENGTH_LIMIT 512 +#define MAX_CELL_SIZE 512 +#define MIN_CELL_SIZE 10 + +/* The maximum number of errors that a cell may get before we + * automatically blow it away (even if the soup isn't full and + * doesn't need reaping). This prevents us wasting valuable CPU + * time on cells which have gone completely AWOL. + */ +#define MAX_ERRORS 100 + +enum cell_state +{ + state_exec, + state_find +}; + +struct cell +{ + struct cell *next; /* Alive cells are linked thru this list. */ + struct cell *prev; /* Alive cells are linked thru this list. */ + struct cell *worse; /* Cells are kept in error order on this list*/ + struct cell *better; /* Cells are kept in error order on this list*/ + reg_t a, b, i, p; /* Registers. */ + reg_t stack[STACK_SIZE]; /* Stack. */ + int sp; /* Stack pointer. */ + int errors; /* Cumulative number of errors encountered */ + enum cell_state state; /* Executing or finding. */ + int dir; /* [Find] -1 = back, 1 = forwards */ + int plen; /* [Find] length of pattern */ + int lim; /* [Find] search limit (counts down to 0) */ + struct soup_frag *frag; /* Fragment in the soup */ + struct cell *daughter; /* Daughter (after MALLOC, before DIVIDE) */ + unsigned long long cycle; /* Number of cycles of runtime. */ + crc_t crc; /* CRC at birth (after mother's DIVIDE). */ + crc_t mother_crc; /* CRC of mother. */ + addr_t fbase; /* Used when saving/loading soup image only. */ +}; + +extern int verbose; + +extern struct cell *cell_malloc (struct state *state, + const struct cell *mother, + struct soup_frag *daughter_frag); +extern void cell_divide (struct state *state, + const struct cell *mother, + struct cell *daughter); +extern void cell_activate (struct state *state, + struct cell *cell); +extern void cell_kill (struct state *state, + struct cell *cell); + +extern void cell_state_load (struct state *state, FILE *fp); +extern void cell_state_save (struct state *state, FILE *fp); + +extern void cell_check (struct state *state); + +extern void exec_insn (struct state *state, struct cell *cell); + +extern void run_thread (struct state *state); + +/* This macro is used to increment the error count in a cell. It + * ensures that the cell ``worst-to-best'' list is kept up to date. + */ +#define INC_ERRORS(state,cell) do { (cell)->errors++; if ((cell)->worse && (cell)->errors > (cell)->worse->errors) _cell_move_worse ((state), (cell)); } while (0) + +extern void _cell_move_worse (struct state *state, struct cell *cell); + +extern struct soup_frag *_cell_get_any_frag (struct state *state); + +extern void _cell_fixup_soup_ref (struct state *state, + addr_t fbase, struct soup_frag *frag); + +#endif /* cell_h */ diff --git a/client.conf b/client.conf new file mode 100644 index 0000000..5bcb134 --- /dev/null +++ b/client.conf @@ -0,0 +1,46 @@ +# DLIFE network client configuration file. + +# Note: You should either set ``server_url'' or set ``server'' +# (possibly both). + +#---------------------------------------------------------------------- +# If set, then the client will download the given web page looking +# for servers to connect to. + +server_url http://dlife.annexia.org/servers.txt + +# If you want the client to only connect to servers in a given +# geographical zone (in order to reduce network traffic), then +# set this to a list of ISO 3166 country codes and/or geographical +# continent codes and/or domain names. +# +# Example (1): The client will only connect to servers in the +# United Kingdom, France and the Netherlands. +# +# server_zone uk fr nl +# +# Example (2): The client will only connect to servers in the +# US or European Union. +# +# server_zone us eu +# +# Example (3): The client will only connect to servers in the +# domain bibliotech.net. +# +# server_zone .bibliotech.net + +#---------------------------------------------------------------------- +# This causes the client to connect directly to the servers listed. +# +# Example: Connect to dlife1.bibliotech.net or dlife2.bibliotech.net. +# +# server dlife1.bibliotech.net dlife2.bibliotech.net + +#---------------------------------------------------------------------- +# How many cells to upload each pass (normally each hour). +# +max_cells_upload_per_pass 6 + +# How many cells to download each pass (normally each hour). +# +max_cells_download_per_pass 4 diff --git a/config.cache b/config.cache new file mode 100644 index 0000000..e69de29 diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..d86b37c --- /dev/null +++ b/config.h.in @@ -0,0 +1,95 @@ +/* config.h.in. Generated automatically from configure.in by autoheader 2.13. */ +#ifndef DLIFE_CONFIG_H +#define DLIFE_CONFIG_H + +#undef PACKAGE +#undef VERSION +#undef SPOOLDIR +#undef CONFDIR + +/* Define if you have the closedir function. */ +#undef HAVE_CLOSEDIR + +/* Define if you have the getpwnam function. */ +#undef HAVE_GETPWNAM + +/* Define if you have the getuid function. */ +#undef HAVE_GETUID + +/* Define if you have the initgroups function. */ +#undef HAVE_INITGROUPS + +/* Define if you have the nice function. */ +#undef HAVE_NICE + +/* Define if you have the opendir function. */ +#undef HAVE_OPENDIR + +/* Define if you have the openlog function. */ +#undef HAVE_OPENLOG + +/* Define if you have the readdir function. */ +#undef HAVE_READDIR + +/* Define if you have the setgid function. */ +#undef HAVE_SETGID + +/* Define if you have the setuid function. */ +#undef HAVE_SETUID + +/* Define if you have the syslog function. */ +#undef HAVE_SYSLOG + +/* Define if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define if you have the header file. */ +#undef HAVE_DIRENT_H + +/* Define if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_GRP_H + +/* Define if you have the header file. */ +#undef HAVE_PWD_H + +/* Define if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Version number of package */ +#undef VERSION + + +#endif /* DLIFE_CONFIG_H */ diff --git a/config.log b/config.log new file mode 100644 index 0000000..42174ee --- /dev/null +++ b/config.log @@ -0,0 +1,20 @@ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +configure:577: checking for a BSD compatible install +configure:630: checking whether build environment is sane +configure:687: checking whether make sets ${MAKE} +configure:733: checking for working aclocal-1.4 +configure:746: checking for working autoconf +configure:759: checking for working automake-1.4 +configure:772: checking for working autoheader +configure:785: checking for working makeinfo +configure:805: checking for gcc +configure:918: checking whether the C compiler (gcc ) works +configure:934: gcc -o conftest conftest.c 1>&5 +configure:960: checking whether the C compiler (gcc ) is a cross-compiler +configure:965: checking whether we are using GNU C +configure:974: gcc -E conftest.c +configure:993: checking whether gcc accepts -g +configure:1036: checking for a BSD compatible install +configure:1089: checking whether make sets ${MAKE} diff --git a/configure b/configure new file mode 100755 index 0000000..37fa179 --- /dev/null +++ b/configure @@ -0,0 +1,1902 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-check Enable extra internal consistency checks (slow)" +ac_help="$ac_help + --enable-profile Enable code profiling" +ac_help="$ac_help + --disable-user-check Do not check for existance of dlife account" +ac_help="$ac_help + --enable-cron[=layout] Install cron script to run dlife net client + 'layout' may be 'auto' (default), 'standard', + or a path to crontab directory starting with / + --disable-cron Do not install cron script" +ac_help="$ac_help + --enable-rc[=layout] Install rc script (runs dlife_soup at boot) + 'layout' may be 'auto' (default), 'standard', + or a path to local rc directory starting with / + --disable-rc Do not install rc script" +ac_help="$ac_help + --with-spool=DIR Spool directory (default typically /var/spool/dlife)" +ac_help="$ac_help + --with-conf=DIR Config directory (default typically /etc/dlife)" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=cell.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +am__api_version="1.4" +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:577: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:630: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:687: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=dlife + +VERSION=1.0.0 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi +cat >> confdefs.h <> confdefs.h <&6 +echo "configure:733: checking for working aclocal-${am__api_version}" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal-${am__api_version} + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal-${am__api_version}" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:746: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake-${am__api_version}""... $ac_c" 1>&6 +echo "configure:759: checking for working automake-${am__api_version}" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake-${am__api_version} + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake-${am__api_version}" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:772: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:785: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + + + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:805: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:835: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:886: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:918: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 929 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:934: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:960: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:965: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:993: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1036: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:1089: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +if test "$CC" = "gcc"; then + CFLAGS="$CFLAGS -Wall -Werror" +fi + +# Check whether --enable-check or --disable-check was given. +if test "${enable_check+set}" = set; then + enableval="$enable_check" + CFLAGS="$CFLAGS -DCHECK=1" + +fi + + +# Check whether --enable-profile or --disable-profile was given. +if test "${enable_profile+set}" = set; then + enableval="$enable_profile" + CFLAGS="$CFLAGS -pg" + +fi + + +# Check whether --enable-user-check or --disable-user-check was given. +if test "${enable_user_check+set}" = set; then + enableval="$enable_user_check" + user_check="no" +else + user_check="yes" + +fi + + +# Check whether --enable-cron or --disable-cron was given. +if test "${enable_cron+set}" = set; then + enableval="$enable_cron" + install_cron="$enableval" +else + install_cron="yes" + +fi + + +# Check whether --enable-rc or --disable-rc was given. +if test "${enable_rc+set}" = set; then + enableval="$enable_rc" + install_rc="$enableval" +else + install_rc="yes" + +fi + + +# Check whether --with-spool or --without-spool was given. +if test "${with_spool+set}" = set; then + withval="$with_spool" + SPOOLDIR="$withval" +else + FC_EXPAND_DIR(SPOOLDIR, '${localstatedir}/spool/dlife') + +fi + + +# Check whether --with-conf or --without-conf was given. +if test "${with_conf+set}" = set; then + withval="$with_conf" + CONFDIR="$withval" +else + FC_EXPAND_DIR(CONFDIR, '${sysconfdir}/dlife') + +fi + + +if test "$user_check" = "yes"; then + echo $ac_n "checking for dlife group""... $ac_c" 1>&6 +echo "configure:1188: checking for dlife group" >&5 + if ! grep '^dlife:' /etc/group >/dev/null; then + { echo "configure: error: there is no 'dlife' group in /etc/group" 1>&2; exit 1; } + fi + echo "$ac_t""found" 1>&6 + + echo $ac_n "checking for dlife user""... $ac_c" 1>&6 +echo "configure:1195: checking for dlife user" >&5 + if ! grep '^dlife:' /etc/passwd >/dev/null; then + { echo "configure: error: there is no 'dlife' user in /etc/passwd" 1>&2; exit 1; } + fi + echo "$ac_t""found" 1>&6 +fi + +for ac_func in \ + closedir \ + getpwnam \ + getuid \ + initgroups \ + nice \ + opendir \ + openlog \ + readdir \ + setgid \ + setuid \ + syslog \ + +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1217: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1245: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1271: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1292: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1309: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1326: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +for ac_hdr in \ + assert.h \ + dirent.h \ + errno.h \ + fcntl.h \ + grp.h \ + pwd.h \ + signal.h \ + stddef.h \ + stdint.h \ + string.h \ + sys/param.h \ + sys/types.h \ + syslog.h \ + time.h \ + unistd.h \ + +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1370: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1380: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + + +echo $ac_n "checking crontab directory""... $ac_c" 1>&6 +echo "configure:1409: checking crontab directory" >&5 + +case "$install_cron" in +yes|auto) + if test -d $sysconfdir/cron.d; then + install_cron=$sysconfdir/cron.d + else + { echo "configure: error: failed to find a directory to put crontabs in; try --help" 1>&2; exit 1; } + fi + ;; +standard) + install_cron=/etc/cron.d + ;; +/*) + ;; +no) + ;; +*) + { echo "configure: error: unknown parameter given to --enable-cron" 1>&2; exit 1; } + ;; +esac + +echo "$ac_t""$install_cron" 1>&6 +CRONDIR=$install_cron + + + +if test "$install_cron" != "no"; then + INSTALL_CRON_TRUE= + INSTALL_CRON_FALSE='#' +else + INSTALL_CRON_TRUE='#' + INSTALL_CRON_FALSE= +fi + + +echo $ac_n "checking rc directory""... $ac_c" 1>&6 +echo "configure:1446: checking rc directory" >&5 + +case "$install_rc" in +yes|auto) + if test -d $sysconfdir/init.d; then + install_rc=$sysconfdir/init.d + else + { echo "configure: error: failed to find a directory to put rc scripts in; try --help" 1>&2; exit 1; } + fi + ;; +standard) + install_rc=/etc/init.d + ;; +/*) + ;; +no) + ;; +*) + { echo "configure: error: unknown parameter given to --enable-rc" 1>&2; exit 1; } + ;; +esac + +echo "$ac_t""$install_rc" 1>&6 +RCDIR=$install_rc + + + +if test "$install_rc" != "no"; then + INSTALL_RC_TRUE= + INSTALL_RC_FALSE='#' +else + INSTALL_RC_TRUE='#' + INSTALL_RC_FALSE= +fi + +echo $ac_n "checking spool directory""... $ac_c" 1>&6 +echo "configure:1482: checking spool directory" >&5 +echo "$ac_t""$SPOOLDIR" 1>&6 + +echo $ac_n "checking config directory""... $ac_c" 1>&6 +echo "configure:1486: checking config directory" >&5 +echo "$ac_t""$CONFDIR" 1>&6 + +echo $ac_n "checking for a place to install documentation""... $ac_c" 1>&6 +echo "configure:1490: checking for a place to install documentation" >&5 +if test -d $prefix/share/doc; then + DOCDIR=$prefix/share/doc/$PACKAGE-$VERSION +else + DOCDIR=/tmp +fi +echo "$ac_t""$DOCDIR" 1>&6 + +RELEASEDATE=`date +"%d %b %Y"` + + + + + + + + +cat >> confdefs.h <> confdefs.h < confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo " + Makefile + dlife_client.pl + dlife_server.pl + dlife.spec + index.html + config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@INSTALL_CRON_TRUE@%$INSTALL_CRON_TRUE%g +s%@INSTALL_CRON_FALSE@%$INSTALL_CRON_FALSE%g +s%@INSTALL_RC_TRUE@%$INSTALL_RC_TRUE%g +s%@INSTALL_RC_FALSE@%$INSTALL_RC_FALSE%g +s%@CRONDIR@%$CRONDIR%g +s%@RCDIR@%$RCDIR%g +s%@SPOOLDIR@%$SPOOLDIR%g +s%@CONFDIR@%$CONFDIR%g +s%@DOCDIR@%$DOCDIR%g +s%@RELEASEDATE@%$RELEASEDATE%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..25b6ac0 --- /dev/null +++ b/configure.in @@ -0,0 +1,252 @@ +# DLIFE (C) 2000 Richard W.M. Jones +# and other authors listed in the ``AUTHORS'' file. +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id: configure.in,v 1.3 2002/04/05 17:02:25 rich Exp $ + +AC_INIT(cell.c) +AM_INIT_AUTOMAKE(dlife, 1.0.0) +AM_CONFIG_HEADER(config.h) + +dnl Check for the basic compile environment. +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_MAKE_SET + +dnl Enable compiler warnings. +if test "$CC" = "gcc"; then + CFLAGS="$CFLAGS -Wall -Werror" +fi + +dnl Check for arguments to configure. +AC_ARG_ENABLE( + check, + [ --enable-check Enable extra internal consistency checks (slow)], + CFLAGS="$CFLAGS -DCHECK=1" +) + +AC_ARG_ENABLE( + profile, + [ --enable-profile Enable code profiling], + CFLAGS="$CFLAGS -pg" +) + +AC_ARG_ENABLE( + user-check, + [ --disable-user-check Do not check for existance of dlife account], + user_check="no", + user_check="yes" +) + +AC_ARG_ENABLE( + cron, + [ --enable-cron[=layout] Install cron script to run dlife net client + 'layout' may be 'auto' (default), 'standard', + or a path to crontab directory starting with / + --disable-cron Do not install cron script], + install_cron="$enableval", + install_cron="yes" +) + +AC_ARG_ENABLE( + rc, + [ --enable-rc[=layout] Install rc script (runs dlife_soup at boot) + 'layout' may be 'auto' (default), 'standard', + or a path to local rc directory starting with / + --disable-rc Do not install rc script], + install_rc="$enableval", + install_rc="yes" +) + +AC_ARG_WITH( + spool, + [ --with-spool=DIR Spool directory (default typically /var/spool/dlife)], + SPOOLDIR="$withval", + FC_EXPAND_DIR(SPOOLDIR, '${localstatedir}/spool/dlife') +) + +AC_ARG_WITH( + conf, + [ --with-conf=DIR Config directory (default typically /etc/dlife)], + CONFDIR="$withval", + FC_EXPAND_DIR(CONFDIR, '${sysconfdir}/dlife') +) + +dnl Check for ``dlife'' account. +if test "$user_check" = "yes"; then + AC_MSG_CHECKING([for dlife group]) + if ! grep '^dlife:' /etc/group >/dev/null; then + AC_MSG_ERROR([there is no 'dlife' group in /etc/group]) + fi + AC_MSG_RESULT([found]) + + AC_MSG_CHECKING([for dlife user]) + if ! grep '^dlife:' /etc/passwd >/dev/null; then + AC_MSG_ERROR([there is no 'dlife' user in /etc/passwd]) + fi + AC_MSG_RESULT([found]) +fi + +dnl Check for available functions. +AC_CHECK_FUNCS( \ + closedir \ + getpwnam \ + getuid \ + initgroups \ + nice \ + opendir \ + openlog \ + readdir \ + setgid \ + setuid \ + syslog \ + ) + +dnl Check for header files. +AC_CHECK_HEADERS( \ + assert.h \ + dirent.h \ + errno.h \ + fcntl.h \ + grp.h \ + pwd.h \ + signal.h \ + stddef.h \ + stdint.h \ + string.h \ + sys/param.h \ + sys/types.h \ + syslog.h \ + time.h \ + unistd.h \ + ) + +dnl Check for a place to install the crontab. +dnl The $install_cron variable will have one of the following possible +dnl values: +dnl yes / auto Try to determine cron dir by automatic means +dnl no Do not install crontab +dnl standard Use FSSTND layout (/etc/cron.d) +dnl /path/to/dir/ Use given directory +dnl After this, $install_cron will contain either a path (beginning +dnl with /) or "no". + +AC_MSG_CHECKING([crontab directory]) + +case "$install_cron" in +yes|auto) + if test -d $sysconfdir/cron.d; then + install_cron=$sysconfdir/cron.d + else + AC_MSG_ERROR([failed to find a directory to put crontabs in; try --help]) + fi + ;; +standard) + install_cron=/etc/cron.d + ;; +/*) + dnl Do nothing. + ;; +no) + dnl Do nothing. + ;; +*) + AC_MSG_ERROR([unknown parameter given to --enable-cron]) + ;; +esac + +AC_MSG_RESULT($install_cron) +CRONDIR=$install_cron + +AM_CONDITIONAL(INSTALL_CRON,[test "$install_cron" != "no"]) + +dnl Check for a place to install rc scripts +dnl The $install_rc variable will have one of the following possible +dnl values: +dnl yes / auto Try to determine rc dir by automatic means +dnl no Do not install rc script +dnl standard Use red hat / debian / FSSTND layout (/etc/init.d) +dnl /path/to/dir/ Use given directory +dnl After this, $install_rc will contain either a path (beginning +dnl with /) or "no". + +AC_MSG_CHECKING([rc directory]) + +case "$install_rc" in +yes|auto) + if test -d $sysconfdir/init.d; then + install_rc=$sysconfdir/init.d + else + AC_MSG_ERROR([failed to find a directory to put rc scripts in; try --help]) + fi + ;; +standard) + install_rc=/etc/init.d + ;; +/*) + dnl Do nothing. + ;; +no) + dnl Do nothing. + ;; +*) + AC_MSG_ERROR([unknown parameter given to --enable-rc]) + ;; +esac + +AC_MSG_RESULT($install_rc) +RCDIR=$install_rc + +AM_CONDITIONAL(INSTALL_RC,[test "$install_rc" != "no"]) + +AC_MSG_CHECKING([spool directory]) +AC_MSG_RESULT($SPOOLDIR) + +AC_MSG_CHECKING([config directory]) +AC_MSG_RESULT($CONFDIR) + +dnl Check for a place to install documentation. +AC_MSG_CHECKING([for a place to install documentation]) +if test -d $prefix/share/doc; then + DOCDIR=$prefix/share/doc/$PACKAGE-$VERSION +else + DOCDIR=/tmp +fi +AC_MSG_RESULT($DOCDIR) + +dnl Release date. +RELEASEDATE=`date +"%d %b %Y"` + +dnl Variables to be substituted. +AC_SUBST(CRONDIR) +AC_SUBST(RCDIR) +AC_SUBST(SPOOLDIR) +AC_SUBST(CONFDIR) +AC_SUBST(DOCDIR) +AC_SUBST(RELEASEDATE) + +dnl Variables to be placed in config.h. +AC_DEFINE_UNQUOTED(SPOOLDIR, "$SPOOLDIR") +AC_DEFINE_UNQUOTED(CONFDIR, "$CONFDIR") + +dnl Generate output files. +AC_OUTPUT([ + Makefile + dlife_client.pl + dlife_server.pl + dlife.spec + index.html + ]) diff --git a/crc.c b/crc.c new file mode 100644 index 0000000..4694400 --- /dev/null +++ b/crc.c @@ -0,0 +1,142 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: crc.c,v 1.1 2002/04/05 14:40:25 rich Exp $ + */ + +#include "config.h" + +#include "crc.h" + +/* Code to do 32-bit CRCs. + * Derived from code by Julian Seward (sewardj@cs.man.ac.uk) + * Written by Richard W.M. Jones (rich@annexia.org) + * Note original copyright messages below ... + */ + +/*-- + Copyright (C) 1996 by Julian Seward. + Department of Computer Science, University of Manchester, + Oxford Road, Manchester M13 9PL, UK. + email: sewardj@cs.man.ac.uk +--*/ + +/*---------------------------------------------------*/ +/*--- 32-bit CRC grunge ---*/ +/*---------------------------------------------------*/ + +/*-- + I think this is an implementation of the AUTODIN-II, + Ethernet & FDDI 32-bit CRC standard. Vaguely derived + from code by Rob Warnock, in Section 51 of the + comp.compression FAQ. +--*/ + +static crc_t crc32Table[256] = { + + /*-- Ugly, innit? --*/ + + 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L, + 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L, + 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L, + 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL, + 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L, + 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L, + 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L, + 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL, + 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L, + 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L, + 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L, + 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL, + 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L, + 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L, + 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L, + 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL, + 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL, + 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L, + 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L, + 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL, + 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL, + 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L, + 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L, + 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL, + 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL, + 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L, + 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L, + 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL, + 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL, + 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L, + 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L, + 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL, + 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L, + 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL, + 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL, + 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L, + 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L, + 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL, + 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL, + 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L, + 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L, + 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL, + 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL, + 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L, + 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L, + 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL, + 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL, + 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L, + 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L, + 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL, + 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L, + 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L, + 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L, + 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL, + 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L, + 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L, + 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L, + 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL, + 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L, + 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L, + 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L, + 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL, + 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L, + 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L +}; + +#define UPDATE_CRC(crcVar,cha) \ +{ \ + crcVar = (crcVar << 8) ^ \ + crc32Table[(crcVar >> 24) ^ \ + (cha)]; \ +} + +inline crc_t +incr_compute_crc32 (crc_t crc, byte_t *p, size_t len) +{ + while (len) + { + UPDATE_CRC (crc, *p); + p ++; + len --; + } + return crc; +} + +crc_t +compute_crc32 (byte_t *p, size_t len) +{ + return incr_compute_crc32 (0xffffffffUL, p, len); +} diff --git a/crc.h b/crc.h new file mode 100644 index 0000000..08db92b --- /dev/null +++ b/crc.h @@ -0,0 +1,33 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: crc.h,v 1.1 2002/04/05 14:40:26 rich Exp $ + */ + +#ifndef crc_h +#define crc_h + +#include + +#include "types.h" + +typedef uint32_t crc_t; + +extern crc_t compute_crc32 (byte_t *p, size_t len); +extern crc_t incr_compute_crc32 (crc_t old_crc, byte_t *p, size_t len); + +#endif /* crc_h */ diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..55a81db --- /dev/null +++ b/debian/changelog @@ -0,0 +1,9 @@ +dlife (0.0.15-1) unstable; urgency=low + + * Initial Release. + + -- Falk Hueffner Fri, 13 Oct 2000 05:49:22 +0200 + +Local variables: +mode: debian-changelog +End: diff --git a/debian/conffiles b/debian/conffiles new file mode 100644 index 0000000..94fdfa9 --- /dev/null +++ b/debian/conffiles @@ -0,0 +1,4 @@ +/etc/init.d/dlife +/etc/dlife/client.conf +/etc/dlife/soup.conf +/etc/ppp/ip-up.d/9dlife diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..b833da7 --- /dev/null +++ b/debian/control @@ -0,0 +1,24 @@ +Source: dlife +Section: misc +Priority: optional +Maintainer: Falk Hueffner +Standards-Version: 3.0.1 + +Package: dlife +Architecture: any +Depends: ${shlibs:Depends}, perl5, libnet-perl, libhtml-parser-perl, liburi-perl, libmime-base64-perl, libdigest-md5-perl, libwww-perl +Description: Distributed Artificial Life client + DLIFE is a distributed version of Tom S. Ray's Tierra artificial life + program. Note that the machine language used is similar to but not + compatible with Tierra. Tom Ray talks about his work (as far as I + know, never completed) to create a ``Digital Reserve''. The DLIFE + project is a development of this. + . + In other words, it's an alternative to the tedious process of cracking + RC5 keys or searching for aliens. You've got a supercomputer on your + desk, let's go and create some life ... + . + It consists of a highly optimized engine for running the artificial + life cells in a virtual machine, written in C, and some Perl scripts + which can upload and download cells from central ``cell-bank'' + servers. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..022b670 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,11 @@ +Distributed Artificial Life was debianized by Falk Hüffner +. + +It was originally downloaded from . There's a web +site for it at http://dlife.annexia.org/. + +The copyright belongs to its author Richard W.M. Jones +. + +It is distributed under the terms of the GNU Public License. The full +text can be found on Debian systems in /usr/share/common-licenses/GPL. diff --git a/debian/cron.d b/debian/cron.d new file mode 100644 index 0000000..bd3cf16 --- /dev/null +++ b/debian/cron.d @@ -0,0 +1,2 @@ +# Run the client to upload cells periodically. +5 * * * * dlife /usr/bin/dlife_client.pl diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..e27bc8b --- /dev/null +++ b/debian/dirs @@ -0,0 +1,3 @@ +usr/bin +usr/sbin +etc/ppp/ip-up.d diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..3c9ddd2 --- /dev/null +++ b/debian/docs @@ -0,0 +1,7 @@ +AUTHORS +README +archproc.gif +archref.html +index.html +machineref.html +servers.txt diff --git a/debian/files b/debian/files new file mode 100644 index 0000000..2596e77 --- /dev/null +++ b/debian/files @@ -0,0 +1 @@ +dlife_0.0.12-1_alpha.deb misc optional diff --git a/debian/init.d b/debian/init.d new file mode 100644 index 0000000..2bc0fa6 --- /dev/null +++ b/debian/init.d @@ -0,0 +1,42 @@ +#! /bin/sh +# +# adapted from the dh_make template by Falk Hueffner +# +# using a pidfile doesn't work unfortunately, since dlife_soup forks +# + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/bin/dlife_soup +NAME=dlife +DESC='distributed artificial life client' + +test -f $DAEMON || exit 0 + +set -e + +case "$1" in + start) + echo -n "Starting $DESC: " + start-stop-daemon --start --quiet --exec $DAEMON + echo "$NAME." + ;; + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --quiet --exec $DAEMON + echo "$NAME." + ;; + restart|force-reload) + echo -n "Restarting $DESC: " + start-stop-daemon --stop --quiet --exec $DAEMON + sleep 1 + start-stop-daemon --start --quiet --exec $DAEMON + echo "$NAME." + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/debian/postinst.debhelper b/debian/postinst.debhelper new file mode 100644 index 0000000..6d6c912 --- /dev/null +++ b/debian/postinst.debhelper @@ -0,0 +1,11 @@ +# Automatically added by dh_installdocs +if [ "$1" = "configure" ]; then + if [ -d /usr/doc -a ! -e /usr/doc/dlife -a -d /usr/share/doc/dlife ]; then + ln -sf ../share/doc/dlife /usr/doc/dlife + fi +fi +# End automatically added section +# Automatically added by dh_installinit +update-rc.d dlife defaults >/dev/null +/etc/init.d/dlife start +# End automatically added section diff --git a/debian/postrm.debhelper b/debian/postrm.debhelper new file mode 100644 index 0000000..a7d2004 --- /dev/null +++ b/debian/postrm.debhelper @@ -0,0 +1,5 @@ +# Automatically added by dh_installinit +if [ "$1" = "purge" ] ; then + update-rc.d dlife remove >/dev/null +fi +# End automatically added section diff --git a/debian/prerm.debhelper b/debian/prerm.debhelper new file mode 100644 index 0000000..ad508d3 --- /dev/null +++ b/debian/prerm.debhelper @@ -0,0 +1,8 @@ +# Automatically added by dh_installdocs +if [ \( "$1" = "upgrade" -o "$1" = "remove" \) -a -L /usr/doc/dlife ]; then + rm -f /usr/doc/dlife +fi +# End automatically added section +# Automatically added by dh_installinit +/etc/init.d/dlife stop +# End automatically added section diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..2e3ef94 --- /dev/null +++ b/debian/rules @@ -0,0 +1,64 @@ +#!/usr/bin/make -f + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +# This is the debhelper compatability version to use. +export DH_COMPAT=1 + +build: build-stamp +build-stamp: + dh_testdir + + ./configure --prefix=/usr --localstatedir=/var --sysconfdir=/etc \ + --disable-cron --disable-rc --disable-user-check + $(MAKE) + + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + -$(MAKE) distclean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + $(MAKE) DESTDIR=`pwd`/debian/tmp install + rm debian/tmp/tmp/* # kludge; installation leaves cruft in /tmp + cp debian/9dlife debian/tmp/etc/ppp/ip-up.d + chmod a+x debian/tmp/etc/ppp/ip-up.d/9dlife + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installdocs + dh_installinit + dh_installcron +# dh_installmanpages + dh_undocumented + dh_installchangelogs + dh_link + dh_strip + dh_compress + dh_fixperms + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/debian/substvars b/debian/substvars new file mode 100644 index 0000000..e530b66 --- /dev/null +++ b/debian/substvars @@ -0,0 +1 @@ +shlibs:Depends=libc6.1 (>= 2.1.2-1) diff --git a/dlife.rc b/dlife.rc new file mode 100644 index 0000000..8b9328f --- /dev/null +++ b/dlife.rc @@ -0,0 +1,49 @@ +#!/bin/sh +# +# dlife.rc This shell script takes care of starting and stopping +# the dlife client. +# +# chkconfig: 2345 80 30 +# description: The Distributed Artificial Life client. +# processname: dlife_soup +# config: /etc/dlife/soup.conf + +# Source function library. +. /etc/init.d/functions + +# Source networking configuration. +. /etc/sysconfig/network + +# Check that networking is up. +[ ${NETWORKING} = "no" ] && exit 0 + +[ -f /usr/bin/dlife_soup ] || exit 0 + +# See how we were called. +case "$1" in + start) + # Start daemons. + echo -n "Starting dlife: " + daemon /usr/bin/dlife_soup + echo + ;; + stop) + # Stop daemons. + echo -n "Shutting down dlife: " + killproc dlife_soup + echo + ;; + restart) + $0 stop + $0 start + ;; + status) + status dlife_soup + ;; + *) + echo "Usage: dlife.rc {start|stop|restart|status}" + exit 1 +esac + +exit 0 + diff --git a/dlife.spec.in b/dlife.spec.in new file mode 100644 index 0000000..0c32c83 --- /dev/null +++ b/dlife.spec.in @@ -0,0 +1,91 @@ +# @configure_input@ +# $Id: dlife.spec.in,v 1.3 2002/04/05 17:07:25 rich Exp $ + +Summary: Distributed Artificial Life (DLIFE) +Name: @PACKAGE@ +Version: @VERSION@ +Release: 1 +Copyright: GPL +Group: Applications/Internet +Source: @PACKAGE@-@VERSION@.tar.gz +BuildRoot: /var/tmp/%{name}-%{version}-root +Requires: perl-libwww-perl +Requires: perl >= 5.004 +Requires: vixie-cron +Requires: SysVinit + + +%description +Distributed Artificial Life is a package for joining your +computer to a network of computers running a large artificial +life simulation. + + +%package server +Summary: Distributed Artificial Life (DLIFE) server +Group: Applications/Internet + + +%description server +This package contains the server code for DLIFE. + + +%prep +%setup -q + + +%build +CFLAGS="-O" \ +./configure \ + --prefix=/usr --sysconfdir=/etc --localstatedir=/var \ + --disable-user-check +make + + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT +make NO_CHOWN=1 DESTDIR=$RPM_BUILD_ROOT install + + +%clean +rm -rf $RPM_BUILD_ROOT + + +%pre +grep '^dlife:' /etc/group >/dev/null || { + echo "There is no 'dlife' group in /etc/group" + exit 1; +} +grep '^dlife:' /etc/passwd >/dev/null || { + echo "There is no 'dlife' user in /etc/passwd" + exit 1; +} + + +%pre server +grep '^dlife:' /etc/group >/dev/null || { + echo "There is no 'dlife' group in /etc/group" + exit 1; +} +grep '^dlife:' /etc/passwd >/dev/null || { + echo "There is no 'dlife' user in /etc/passwd" + exit 1; +} + + +%files +%defattr(-,root,root) +%doc /usr/share/doc/@PACKAGE@-@VERSION@/ +@prefix@/bin/dlife_soup +@prefix@/bin/dlife_client.pl +%attr(0775,dlife,dlife) @SPOOLDIR@/ +@CONFDIR@/ +%config @CRONDIR@/dlife_client.cron +@RCDIR@/dlife.rc + + +%files server +%defattr(-,root,root) +@prefix@/bin/dlife_server.pl +%attr(0775,dlife,dlife) @SPOOLDIR@/store/ diff --git a/dlife_asm.pl b/dlife_asm.pl new file mode 100644 index 0000000..1a245c9 --- /dev/null +++ b/dlife_asm.pl @@ -0,0 +1,356 @@ +#!/usr/bin/perl -w + +# DLIFE assembler. +# By Richard W.M. Jones. +# +# $Id: dlife_asm.pl,v 1.1 2002/04/05 14:40:26 rich Exp $ + +use strict; + +use Getopt::Long; + +my $help; + +GetOptions ("help|?" => \$help); + +if ($help) + { + print STDERR "dlife_asm.pl [--help] file.dla [file.dla [...]]\n"; + exit 1; + } + +# Read input file(s) and assemble each one. Each input file has the +# form ``filename.dla'' and we will write a file called ``filename.dlo''. +foreach my $filename (@ARGV) + { + my $output = $filename . ".dlo"; + + if ($filename =~ m/(.*)\.dla$/) + { + $output = $1 . ".dlo"; + } + + open FILE, "<$filename" or die "$filename: $!"; + open OUT, ">$output" or die "$output: $!"; + + while () + { + # Remove terminating CRs and LFs. + s/[\n\r]+//; + + # Ignore blank lines and comments. + s/;.*$//; + s/^[ \t]*$//; + next if m/^$/; + + # Parse the instruction. + parse_insn ($_); + } + + close FILE; + print OUT "\n"; + close OUT; + } + +sub parse_insn + { + my $insn = shift; + + # Trim leading and trailing whitespace. + $insn =~ s/^[ \t]+//g; + $insn =~ s/[ \t]+$//g; + + # Leading label? + if ($insn =~ m/^([01]+):(.*)$/) + { + my $label = $1; + my $rest = $2; + + foreach (split //, $label) + { + if (m/0/) { print OUT "00" } + if (m/1/) { print OUT "01" } + } + + parse_insn ($rest); + return; + } + + # IFZ instruction prefix? + if ($insn =~ m/^IFZ[ \t]+(.*)$/i) + { + my $rest = $1; + + print OUT "07\n"; + + parse_insn ($rest); + return; + } + # Empty instruction? + elsif ($insn =~ m/^$/) + { + return; + } + # Other instruction? + elsif ($insn =~ m/^NOP0$/i) + { + print OUT "00\n"; + } + elsif ($insn =~ m/^NOP1$/i) + { + print OUT "01\n"; + } + elsif ($insn =~ m/^INC[ \t]+A$/i) + { + print OUT "02\n"; + } + elsif ($insn =~ m/^DEC[ \t]+A$/i) + { + print OUT "03\n"; + } + elsif ($insn =~ m/^SHL[ \t]+A$/i) + { + print OUT "04\n"; + } + elsif ($insn =~ m/^FINDB[ \t](.*)$/i) + { + print OUT "08\n"; + parse_pattern ($1); + } + elsif ($insn =~ m/^FINDF[ \t](.*)$/i) + { + print OUT "09\n"; + parse_pattern ($1); + } + elsif ($insn =~ m/^MALLOC$/i) + { + print OUT "0A\n"; + } + elsif ($insn =~ m/^DIVIDE$/i) + { + print OUT "0B\n"; + } + elsif ($insn =~ m/^MOVE[ \t]+\[I\],A$/i) + { + print OUT "0C\n"; + } + elsif ($insn =~ m/^MOVE[ \t]+A,\[I\]$/i) + { + print OUT "0D\n"; + } + elsif ($insn =~ m/^DMOVE[ \t]+\[I\],A$/i) + { + print OUT "0E\n"; + } + elsif ($insn =~ m/^DMOVE[ \t]+A,\[I\]$/i) + { + print OUT "0F\n"; + } + elsif ($insn =~ m/^XOR[ \t]+([ABIP]),([ABIP])$/i) + { + my $reg1 = reg2bin ($1); + my $reg2 = reg2bin ($2); + + printf OUT ("%02X\n", 16 + ($reg2 << 2) + $reg1); + } + elsif ($insn =~ m/^PUSH[ \t]+([ABIP])$/i) + { + my $reg = reg2bin ($1); + + printf OUT ("%02X\n", 32 + $reg); + } + elsif ($insn =~ m/^POP[ \t]+([ABIP])$/i) + { + my $reg = reg2bin ($1); + + printf OUT ("%02X\n", 36 + $reg); + } + # Instruction set macros. + elsif ($insn =~ m/MOVE[ \t]+([ABIP]),([ABIP])$/i) + { + my $reg1 = reg2bin ($1); + my $reg2 = reg2bin ($2); + + printf OUT ("%02X", 32 + $reg1); # PUSH reg1 + printf OUT ("%02X\n", 36 + $reg2); # POP reg2 + } + elsif ($insn =~ m/SWAP[ \t]+([ABIP]),([ABIP])$/i) + { + my $reg1 = reg2bin ($1); + my $reg2 = reg2bin ($2); + + printf OUT ("%02X", 16 + ($reg2 << 2) + $reg1); # XOR reg1, reg2 + printf OUT ("%02X", 16 + ($reg1 << 2) + $reg2); # XOR reg2, reg1 + printf OUT ("%02X", 16 + ($reg2 << 2) + $reg1); # XOR reg1, reg2 + printf OUT ("%02X\n", 16 + ($reg1 << 2) + $reg2); # XOR reg2, reg1 + } + elsif ($insn =~ m/ZERO[ \t]+([ABIP])$/i) + { + my $reg = reg2bin ($1); + + printf OUT ("%02X\n", 16 + ($reg << 2) + $reg); # XOR reg, reg + } + elsif ($insn =~ m/ADD[ \t]+([0-9]+),A$/i) + { + my $n = $1; + + for (my $i = 0; $i < $n; ++$i) + { + print OUT "02"; + } + print OUT "\n"; + } + elsif ($insn =~ m/MOVE[ \t]+([0-9]+),A$/i) + { + my $n = $1; + + print OUT "10"; # XOR A,A + while ($n > 0) + { + if (($n & 1) == 1) + { + print OUT "0402"; # SHL A; INC A + } + else + { + print OUT "04"; # SHL A + } + $n >>= 1; + } + print OUT "\n"; + } + elsif ($insn =~ m/LOAD[ \t]+([0-9]+),A$/i) + { + my $n = $1; + + print OUT "222124"; # PUSH I; PUSH B; POP A + for (my $i = 0; $i < $n * 2; ++$i) + { + print OUT "02"; # INC A + } + print OUT "20260E26\n"; # PUSH A; POP I; DMOVE [I],A; POP I + } + elsif ($insn =~ m/STORE[ \t]+A,([0-9]+)$/i) + { + my $n = $1; + + print OUT "22202124"; # PUSH I; PUSH A; PUSH B; POP A + for (my $i = 0; $i < $n * 2; ++$i) + { + print OUT "02"; # INC A + } + print OUT "2026240F26\n"; # PUSH A; POP I; POP A; DMOVE A,[I]; POP I + } + elsif ($insn =~ m/^JMP[ \t]+I$/i) + { + print OUT "2227\n"; # PUSH I; POP P + } + elsif ($insn =~ m/^JMPF[ \t](.*)$/i) + { + print OUT "09"; # FINDF + parse_pattern ($1); + print OUT "2227\n"; # PUSH I; POP P + } + elsif ($insn =~ m/^JMPB[ \t](.*)$/i) + { + print OUT "08"; # FINDB + parse_pattern ($1); + print OUT "2227\n"; # PUSH I; POP P + } + elsif ($insn =~ m/^JMPZF[ \t](.*)$/i) + { + print OUT "09"; # FINDF + parse_pattern ($1); + print OUT "22072726\n"; # PUSH I; IFZ POP P; POP I + } + elsif ($insn =~ m/^JMPZB[ \t](.*)$/i) + { + print OUT "08"; # FINDB + parse_pattern ($1); + print OUT "22072726\n"; # PUSH I; IFZ POP P; POP I + } + elsif ($insn =~ m/^CALLF[ \t](.*)$/i) + { + print OUT "2309"; # PUSH P; FINDF + parse_pattern ($1); + print OUT "2227\n"; # PUSH I; POP P + } + elsif ($insn =~ m/^CALLB[ \t](.*)$/i) + { + print OUT "2308"; # PUSH P; FINDB + parse_pattern ($1); + print OUT "2227\n"; # PUSH I; POP P + } + elsif ($insn =~ m/^RET[ \t]+([0-9]+)$/i) + { + my $n = $1; + print OUT "24"; # POP A + for (my $i = 0; $i < $n + 3; ++$i) + { + print OUT "02"; # INC A + } + print OUT "2027\n"; # PUSH A; POP P + } + elsif ($insn =~ m/^DB[ \t]+([0-9]+)$/i) + { + my $n = $1; + for (my $i = 0; $i < $n; ++$i) + { + print OUT "FF"; + } + print OUT "\n"; + } + elsif ($insn =~ m/^DW[ \t]+([0-9]+)$/i) + { + my $n = $1; + for (my $i = 0; $i < $n * 2; ++$i) + { + print OUT "FF"; + } + print OUT "\n"; + } + else + { + die "$insn: unknown instruction"; + } + } + +sub parse_pattern + { + my $pattern = shift; + + if ($pattern =~ m/^([01]+)$/) + { + foreach (split //, $1) + { + if (m/0/) { print OUT "00" } + if (m/1/) { print OUT "01" } + } + } + elsif ($pattern =~ m/^~([01]+)$/) # Complemented pattern. + { + foreach (split //, $1) + { + if (m/0/) { print OUT "01" } + if (m/1/) { print OUT "00" } + } + } + else + { + die "$pattern: unrecognized pattern argument"; + } + } + +sub reg2bin + { + my $reg = shift; + + if (uc($reg) eq "A") { return 0 } + elsif (uc($reg) eq "B") { return 1 } + elsif (uc($reg) eq "I") { return 2 } + elsif (uc($reg) eq "P") { return 3 } + else + { + die "$reg: unknown register name"; + } + } diff --git a/dlife_client.cron b/dlife_client.cron new file mode 100644 index 0000000..bd3cf16 --- /dev/null +++ b/dlife_client.cron @@ -0,0 +1,2 @@ +# Run the client to upload cells periodically. +5 * * * * dlife /usr/bin/dlife_client.pl diff --git a/dlife_client.pl.in b/dlife_client.pl.in new file mode 100644 index 0000000..bf34757 --- /dev/null +++ b/dlife_client.pl.in @@ -0,0 +1,397 @@ +#!/usr/bin/perl -w -T +# -*- perl -*- +# @configure_input@ + +use strict; + +use Getopt::Long; +use LWP::UserAgent; +use Socket; +use IO::Socket; +use Sys::Hostname; +use Sys::Syslog qw(:DEFAULT setlogsock); + +my $help; +my $verbose; +my $config_filename = "@CONFDIR@/client.conf"; +my $spooldir = "@SPOOLDIR@"; +my $client_version = "@VERSION@"; + +GetOptions ("help|?" => \$help, + "verbose" => \$verbose, + "config=s" => \$config_filename, + "spooldir=s" => \$spooldir); + +if ($help) + { + print STDERR <) + { + s/[\n\r]*$//; + next if /^\s*\#/; + next if /^\s*$/; + + if (/^\s*server_url\s+(\S+)\s*$/) + { + $server_url = $1; + print "server_url=$server_url\n" if $verbose; + } + elsif (/^\s*server_zone\s+(.*)\s*$/) + { + @server_zones = split /\s+/, $1; + print "server_zones=", join (" ", @server_zones), "\n" if $verbose; + } + elsif (/^\s*server\s+(.*)\s*$/) + { + @servers = split /\s+/, $1; + print "servers=", join (" ", @servers), "\n" if $verbose; + } + elsif (/^\s*max_cells_upload_per_pass\s+([1-9][0-9]*)\s*$/) + { + $max_cells_upload_per_pass = $1; + } + elsif (/^\s*max_cells_download_per_pass\s+([1-9][0-9]*)\s*$/) + { + $max_cells_download_per_pass = $1; + } + else + { + die "unknown configuration option: $_"; + } + } + +close CONFIG; + +# Load @server_zones into a hash for rapid searching. +my %server_zones; +foreach (@server_zones) { $server_zones{$_} = 1; } + +# Server URL set or @servers not empty? +unless ($server_url || @servers) + { + die "neither server_url and servers was set: cannot do anything"; + } + +# Go to spool directory. +chdir $spooldir or die "$spooldir: $!"; + +# Find the list of cells to upload and arrange into a random order. +my @all_upload_cells = randomize_list (glob_outgoing ()); + +unless (@all_upload_cells) + { + syslog ("info", "no cells to upload (is the dlife_soup process running?)"); + exit; + } + +# Only upload the first few cells. +my @upload_cells = @all_upload_cells; +splice @upload_cells, $max_cells_upload_per_pass; + +# If server URL set, then go and download the webpage. Load appropriate +# server names into @servers. +if ($server_url) + { + syslog ("info", "contacting $server_url"); + print "Contacting $server_url\n" if $verbose; + + my $ua = LWP::UserAgent->new; + my $req = HTTP::Request->new ("GET", $server_url); + my $rep = $ua->request ($req); + + if ($rep->is_success) + { + print "Fetched page. Parsing page ...\n" if $verbose; + + # Parse the page. + my @lines = split /[\n\r]+/, $rep->content; + + foreach (@lines) + { + if (/^\s*server\s+(\S*)\s+(.*)\s*$/) + { + my $server = $1; + my @zones = split /\s+/, $2; + + # Is this server in one of our zones? + if (@server_zones) + { + foreach (@zones) + { + if (exists $server_zones{$_}) + { + push @servers, $server; + last; + } + } + } + else + { + push @servers, $server; + } + } + } + + print "Finished parsing page. \@servers = ", + join (" ", @servers), "\n" + if $verbose; + } + else + { + syslog ("error", "could not contact $server_url"); + print "Could not contact server.\n" if $verbose; + } + } + +# Sort the server list into a random order. +@servers = randomize_list (@servers); + +# Contact each server in turn until we succeed with one of them. +my $server; + +foreach $server (@servers) + { + alarm 0; + + print "Attempting to connect to $server port 5904\n" if $verbose; + syslog ("info", "exchanging cells with $server"); + + my $socket = new IO::Socket::INET (PeerAddr => $server, + PeerPort => "5904", + Proto => "tcp"); + + unless ($socket) + { + syslog ("error", "could not connect to $server"); + print "Failed to connect.\n" if $verbose; + next; + } + + print "Connected.\n" if $verbose; + + # Read server and protocol version. + alarm 60; + $_ = $socket->getline; + + unless (/^DLIFE SERVER\s+([0-9]+\.[0-9]+)\s+([0-9]+\.[0-9]+)/) + { + print "Unrecognized server greeting.\n" if $verbose; + next; + } + + my $server_version = $1; + my $protocol_version = $2; + + # The only protocol we recognize right now is version 1.x. These + # x (minor) revisions will be backwards compatible. If an + # incompatibility is introduced in the future, then that will + # become version 2.x, 3.x, etc. + unless ($protocol_version =~ /^1\./) + { + print "Unsupported protocol version.\n" if $verbose; + next; + } + + # Send our client greeting string. + $socket->print ("HELO - $client_version\r\n"); + + # Wait for OK response. + alarm 60; + $_ = $socket->getline; + + unless (/^2[0-9][0-9]\s/) + { + print "Error response from server during HELO.\n" if $verbose; + next; + } + + # Check for cells to upload, and upload the first few. + my $cell_filename; + + foreach $cell_filename (@upload_cells) + { + print "Uploading $cell_filename ...\n" if $verbose; + + $socket->print ("STOR\r\n"); + + # Wait for OK to send response. + alarm 60; + $_ = $socket->getline; + + unless (/^1[0-9][0-9]\s/) + { + print "Error response from server during STOR.\n" if $verbose; + next; + } + + # Send the cell. + open CELL, "<$cell_filename" or die "$cell_filename: $!"; + + while () + { + s/[\n\r]*$//; + $socket->print ($_, "\r\n"); + } + + close CELL; + + $socket->print (".\r\n"); + + # Wait for OK response from server. + alarm 60; + $_ = $socket->getline; + + unless (/^2[0-9][0-9]\s/) + { + print "Error response from server after STOR.\n" if $verbose; + next; + } + } + + # Remove all upload cells in the queue. + foreach $cell_filename (@all_upload_cells) + { + unlink $cell_filename; + } + + # Check for cells to download. + for (my $i = 0; $i < $max_cells_download_per_pass; ++$i) + { + print "Downloading ...\n" if $verbose; + + $socket->print ("RETR\r\n"); + + # Wait for OK to retrieve response. + alarm 60; + $_ = $socket->getline; + + unless (/^1[0-9][0-9]\s/) + { + print "Error response from server during RETR.\n" if $verbose; + next; + } + + # Retrieve the cell. + my $cell = ""; + + while (length ($cell) < 8192) + { + alarm 10; + $_ = $socket->getline; + alarm 0; + + s/[\n\r]*$//; + + last if $_ eq "."; + + $cell .= $_ . "\n"; + } + + # Wait for OK response. + alarm 60; + $_ = $socket->getline; + + unless (/^2[0-9][0-9]\s/) + { + print "Error response from server after RETR.\n" if $verbose; + next; + } + + # Save the cell to a file. + my $rand = int (rand 1000000000); + open CELL, ">incoming/$rand.dlo" or die "incoming/$rand.dlo: $!"; + + print CELL $cell; + + close CELL; + } + + print "Disconnecting ...\n" if $verbose; + + # Say goodbye. + $socket->print ("QUIT\r\n"); + + # Wait for OK response from server. + alarm 60; + $_ = $socket->getline; + + unless (/^2[0-9][0-9]\s/) + { + print "Error response from server during QUIT.\n" if $verbose; + next; + } + + # Close socket. + $socket->close; + + alarm 0; + last; + } + +syslog ("info", "exit"); + +exit; + +sub randomize_list + { + for (my $i = 0; $i < @_; ++$i) + { + my $r = int (rand (@_ - $i)); + + if ($r > 0) + { + # Swap elements $i and $i+$r. + my $t = $_[$i+$r]; + $_[$i+$r] = $_[$i]; + $_[$i] = $t; + } + } + + return @_; + } + +# This function is equivalent to glob ("outgoing/*.dlo"), except that +# the glob function doesn't work when tainting is enabled, alas. +sub glob_outgoing + { + opendir DIR, "outgoing" or die "outgoing: $!"; + my @names = map { untaint_string ($_) } map { "outgoing/$_" } grep { /\.dlo$/ } readdir DIR; + closedir DIR; + return @names; + } + +sub untaint_string + { + my $s = shift; + $s =~ /^(.*)$/; + return $1; + } diff --git a/dlife_disasm.pl b/dlife_disasm.pl new file mode 100755 index 0000000..a9c305e --- /dev/null +++ b/dlife_disasm.pl @@ -0,0 +1,147 @@ +#!/usr/bin/perl -w + +# DLIFE disassembler. +# By Richard W.M. Jones. +# +# $Id: dlife_disasm.pl,v 1.1 2002/04/05 14:40:26 rich Exp $ + +use strict; + +use Getopt::Long; + +my $help; + +GetOptions ("help|?" => \$help); + +if ($help) + { + printf STDERR "dlife_disasm.pl [--help] [file.dlo] > file.dla\n"; + exit 1; + } + +# Read the entire input file into memory so that we can do some +# clever stuff with string regexes. +my $code = ""; + +while (<>) + { + $code .= $_; + } + +# Remove anything which isn't [0-9a-f]. +$code =~ tr/0-9a-fA-F//cd; +$code =~ tr/a-f/A-F/; + +# Convert code to . +$code =~ s/(..)/<$1>/g; + +# NOTE: The order of this substitutions IS important. + +# CALLB and CALLF macros. +$code =~ s/<23>(<08>|<09>)((<00>|<01>)+)<22><27>/convert_call ($1, $2)/ge; + +# JMPB and JMPF macros. +$code =~ s/(<08>|<09>)((<00>|<01>)+)<22><27>/convert_jmp ($1, $2)/ge; + +# JMPBZ and JMPFZ macros. +$code =~ s/(<08>|<09>)((<00>|<01>)+)<22><07><27><26>/convert_jmpz ($1, $2)/ge; + +# Basic FINDF and FINDB commands. +$code =~ s/(<08>|<09>)((<00>|<01>)+)/convert_find ($1, $2)/ge; + +# Any other patterns are labels. +$code =~ s/((<00>|<01>)+)/convert_label ($1)/ge; + +# MOVE macro. +$code =~ s/(<2[0-3]>)(<2[4-7]>)/convert_move ($1, $2)/ge; + +# SWAP macro. XXX Difficult ... + + + + + + + +print $code; + +sub convert_call + { + my $find_code = shift; + my $pattern = shift; + + my $insn = $find_code eq "<08>" ? "CALLB" : "CALLF"; + + $pattern =~ s/<00>/1/g; # Pattern is complemented. + $pattern =~ s/<01>/0/g; + + return "\n\t$insn ~$pattern\n"; + } + +sub convert_jmp + { + my $find_code = shift; + my $pattern = shift; + + my $insn = $find_code eq "<08>" ? "JMPB" : "JMPF"; + + $pattern =~ s/<00>/1/g; # Pattern is complemented. + $pattern =~ s/<01>/0/g; + + return "\n\t$insn ~$pattern\n"; + } + +sub convert_jmpz + { + my $find_code = shift; + my $pattern = shift; + + my $insn = $find_code eq "<08>" ? "JMPBZ" : "JMPFZ"; + + $pattern =~ s/<00>/1/g; # Pattern is complemented. + $pattern =~ s/<01>/0/g; + + return "\n\t$insn ~$pattern\n"; + } + +sub convert_find + { + my $find_code = shift; + my $pattern = shift; + + my $insn = $find_code eq "<08>" ? "FINDB" : "FINDF"; + + $pattern =~ s/<00>/1/g; # Pattern is complemented. + $pattern =~ s/<01>/0/g; + + return "\n\t$insn ~$pattern\n"; + } + +sub convert_label + { + my $pattern = shift; + + $pattern =~ s/<00>/0/g; + $pattern =~ s/<01>/1/g; + + return "\n$pattern:\n"; + } + +sub convert_move + { + my $push_code = shift; + my $pop_code = shift; + + my ($src, $dst); + if ($push_code eq "<20>") { $src = "A" } + elsif ($push_code eq "<21>") { $src = "B" } + elsif ($push_code eq "<22>") { $src = "I" } + elsif ($push_code eq "<23>") { $src = "P" } + if ($pop_code eq "<24>") { $dst = "A" } + elsif ($pop_code eq "<25>") { $dst = "B" } + elsif ($pop_code eq "<26>") { $dst = "I" } + elsif ($pop_code eq "<27>") { $dst = "P" } + + return "\n\tMOVE $src,$dst\n"; + } + diff --git a/dlife_server.pl.in b/dlife_server.pl.in new file mode 100644 index 0000000..9596888 --- /dev/null +++ b/dlife_server.pl.in @@ -0,0 +1,222 @@ +#!/usr/bin/perl -w -T +# -*- perl -*- +# @configure_input@ + +BEGIN { + # Close stderr, else inetd sends this back to the client. + close STDERR; +}; + +use strict; + +use Socket; +use IO::Socket; +use Sys::Hostname; +use Sys::Syslog qw(:DEFAULT setlogsock); + +$ENV{PATH} = "/usr/bin:/bin"; +delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; + +my $spooldir = "@SPOOLDIR@"; +my $user = "dlife"; +my $server_version = "@VERSION@"; +my $protocol_version = "1.0"; +my $cells_uploaded = 0; +my $cells_downloaded = 0; +my $max_cells_upload_per_pass = 8; +my $max_cells_download_per_pass = 8; + +my $hostname = hostname (); + +# Open a connection to syslog. +setlogsock ("unix"); +openlog ("dlife_server", "pid,ndelay", "user"); + +# Chroot into the spool directory and change our UID/GID so we are safe. +my ($login, $pass, $uid, $gid) = getpwnam ($user) + or die "$user: user not found in password file"; + +chroot $spooldir or die "chroot $spooldir: $!"; + +$) = $gid; +$> = $uid; + +die "could not change UID successfully: $!" unless $> == $uid && $) == $gid; + +chdir "/store" or die "$spooldir/store: $!"; + +# Pull out connection information. +my $peername = getpeername STDIN; +my ($peerport, $peeraddr) = unpack_sockaddr_in ($peername); +my $peeraddrstring = inet_ntoa ($peeraddr); + +my $peerhostname; + +my $revhostname = gethostbyaddr ($peeraddr, AF_INET); +if ($revhostname) + { + my $ipaddr = gethostbyname ($revhostname); + + if ($ipaddr && inet_ntoa ($ipaddr) eq $peeraddrstring) + { + $peerhostname = $revhostname; + } + } + +# Log connection information. +syslog ("info", "received connection from $peeraddrstring:$peerport" . + ($peerhostname ? " ($peerhostname)" : "")); + +$| = 1; + +# Send greeting to client. +print "DLIFE SERVER $server_version $protocol_version\r\n"; + +# Loop, waiting for commands from the client. +for (;;) + { + alarm 60; + $_ = ; + + # Remove trailing \r\n. + s/[\r\n]+$//; + + if (/^HELO\s+(.*)\s+(.*)$/) + { + do_HELO_command ($1, $2); + } + elsif (/^STOR$/) + { + do_STOR_command (); + } + elsif (/^RETR$/) + { + do_RETR_command (); + } + elsif (/^QUIT$/) + { + print "200 Goodbye.\r\n"; + last; # Exit the loop. + } + else + { + # Unknown command. Return an error message. + print "500 Unknown command.\r\n"; + } + } + +exit 0; + +sub do_HELO_command + { + my $remote_hostname = shift; + my $remote_client_version = shift; + + syslog ("info", "client software version: $remote_client_version"); + + # Do nothing with this information for now. + print "200 Hello.\r\n"; + } + +sub do_STOR_command + { + if ($cells_uploaded > $max_cells_upload_per_pass) + { + print "500 Too many cells uploaded in this pass.\r\n"; + return; + } + + print "100 OK. Send the cell, terminated by . on a line of its own.\r\n"; + + # Read in the cell. + my $cell = ""; + + while (length ($cell) < 8192) + { + alarm 10; + $_ = ; + alarm 0; + + s/[\n\r]*$//; + + last if $_ eq "."; + + $cell .= $_ . "\n"; + } + + # Save the cell to a file. + my $rand = int (rand 1000000000); + open CELL, ">$rand.dlo" or die "$rand.dlo: $!"; + + print CELL $cell; + + close CELL; + + syslog ("info", "received cell $rand.dlo"); + + $cells_uploaded ++; + print "200 Cell uploaded OK.\r\n"; + } + +sub do_RETR_command + { + if ($cells_downloaded > $max_cells_download_per_pass) + { + print "500 Too many cells downloaded in this pass.\r\n"; + return; + } + + # Find a cell at random. + my @cells = glob_cells (); + if (@cells == 0) + { + print "400 I have no cells to send you. Try again later.\r\n"; + return; + } + + my $r = rand @cells; + my $cell_filename = $cells[$r]; + + unless (open CELL, "<$cell_filename") + { + print "400 Another process grabbed that cell before I could send it. Try again.\r\n"; + return; + } + + # Send it. + print "100 OK. Sending you a cell now.\r\n"; + + syslog ("info", "sending cell $cell_filename"); + + while () + { + s/[\n\r]+$//; + print $_, "\r\n"; + } + + close CELL; + + unlink $cell_filename; + + print ".\r\n"; + + $cells_downloaded ++; + print "200 Finished sending the cell.\r\n"; + } + +# This function is equivalent to glob ("*.dlo"), except that +# the glob function doesn't work when tainting is enabled, alas. +sub glob_cells + { + opendir DIR, "." or die "$spooldir/store: $!"; + my @names = map { untaint_string ($_) } grep { /\.dlo$/ } readdir DIR; + closedir DIR; + return @names; + } + +sub untaint_string + { + my $s = shift; + $s =~ /^(.*)$/; + return $1; + } diff --git a/dlink.h b/dlink.h new file mode 100644 index 0000000..2d4f061 --- /dev/null +++ b/dlink.h @@ -0,0 +1,146 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: dlink.h,v 1.1 2002/04/05 14:40:26 rich Exp $ + */ + +#ifndef dlink_h +#define dlink_h + +/* This was snarfed from the source for Python 1.5. */ +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifndef offsetof +#define offsetof(type, member) ( (int) & ((type*)0) -> member ) +#endif + +typedef struct dlink_list_element +{ + void *next; + void *prev; +} dlink_list_element_t; + +typedef struct dlink_list +{ + void *first; + void *last; + int offset; +} dlink_list_t; + +#define DLINK_LIST_INIT(offset) { 0, 0, (offset) } + +#define _DLINK_ELEMENT_PTRS(element,list) ((dlink_list_element_t *) ((element) + (list)->offset)) +#define _DLINK_FIRST_PTRS(list) _DLINK_ELEMENT_PTRS((list)->first,(list)) +#define _DLINK_LAST_PTRS(list) _DLINK_ELEMENT_PTRS((list)->last,(list)) + +extern inline void +dlink_list_init (dlink_list_t *list, int offset) +{ + list->first = list->last = 0; + list->offset = offset; +} + +extern inline void +insert_before_first (void *element, dlink_list_t *list) +{ + dlink_list_element_t *eptrs = _DLINK_ELEMENT_PTRS (element, list); + + eptrs->prev = 0; + eptrs->next = list->first; + if (list->first) + _DLINK_FIRST_PTRS(list)->prev = element; + else + list->last = element; + list->first = element; +} + +extern inline void +insert_before_last (void *element, dlink_list_t *list) +{ + dlink_list_element_t *eptrs = _DLINK_ELEMENT_PTRS (element, list); + + eptrs->next = 0; + eptrs->prev = list->last; + if (list->last) + _DLINK_LAST_PTRS(list)->next = element; + else + list->first = element; + list->last = element; +} + +extern inline void +move_towards_last (void *e, dlink_list_t *list) +{ + dlink_list_element_t *eptrs = _DLINK_ELEMENT_PTRS (e, list); + + void *e0 = eptrs->prev; + dlink_list_element_t *e0ptrs = _DLINK_ELEMENT_PTRS (e0, list); + + void *e1 = eptrs->next; + dlink_list_element_t *e1ptrs = _DLINK_ELEMENT_PTRS (e1, list); + + void *e2 = e1ptrs->next; + dlink_list_element_t *e2ptrs = _DLINK_ELEMENT_PTRS (e2, list); + + /* The elements are: e0 <---> e <---> e1 <---> e2. + * + * We know that e and e1 exist, but e0 and e2 may or may not exist. + * + * We want the arrangement to be: + * e0 <---> e1 <---> e <---> e2. + */ + e1ptrs->prev = e0; + if (e0) + e0ptrs->next = e1; + else + list->first = e1; + + e1ptrs->next = e; + eptrs->prev = e1; + + eptrs->next = e2; + if (e2) + e2ptrs->prev = e; + else + list->last = e; +} + +extern inline void +remove_element (void *element, dlink_list_t *list) +{ + dlink_list_element_t *eptrs = _DLINK_ELEMENT_PTRS (element, list); + + void *eprev = eptrs->prev; + dlink_list_element_t *eprevptrs = _DLINK_ELEMENT_PTRS (eprev, list); + + void *enext = eptrs->next; + dlink_list_element_t *enextptrs = _DLINK_ELEMENT_PTRS (enext, list); + + if (eptrs->next) + enextptrs->prev = eprev; + else + list->last = eprev; + + if (eptrs->prev) + eprevptrs->next = enext; + else + list->first = enext; +} + +#endif /* dlink_h */ diff --git a/exec.c b/exec.c new file mode 100644 index 0000000..2f8b6a3 --- /dev/null +++ b/exec.c @@ -0,0 +1,556 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: exec.c,v 1.2 2002/04/05 16:47:12 rich Exp $ + */ + +#include "config.h" + +#include + +#include "cell.h" +#include "random.h" +#include "params.h" +#include "soup.h" + +#define TRACE 0 + +#if TRACE +static void trace (const struct cell *cell, int insn); +#endif + +unsigned long long cell_cycle = 0; + +static inline int +get_pattern_length (struct state *state, const struct cell *cell) +{ + int p = cell->p; + int c; + + /* XXX Maximum pattern length? */ + /* XXX What if pattern exceeds limits of the cell? */ + while ((c = get_soup (state, cell->frag, p) & 0x3F) == 0 || c == 1) + { + p++; + } + + return p - cell->p; +} + +static inline int +check_access (struct state *state, const struct cell *cell, reg_t raddr) +{ + if (raddr >= 0 && raddr < cell->frag->len) /* In mother? */ + return 1; + if (cell->daughter) /* In daughter? */ + { + int offset = cell->daughter->frag->base - cell->frag->base; + + /* Be careful with the wrap-around case here. */ + if (((raddr - offset) & (state->soup_size - 1)) >= 0 && + ((raddr - offset) & (state->soup_size - 1)) < cell->daughter->frag->len) + return 1; + } + return 0; +} + +static inline int +check_exec_access (struct state *state, const struct cell *cell, reg_t raddr) +{ + if (raddr >= 0 && raddr < cell->frag->len) /* In mother? */ + return 1; + return 0; +} + +static inline void +push (struct cell *cell, reg_t v) +{ + cell->sp = (cell->sp+1) & (STACK_SIZE-1); + cell->stack[cell->sp] = v; +} + +static inline void +pop (struct cell *cell, reg_t *va) +{ + *va = cell->stack[cell->sp]; + cell->sp = (cell->sp-1) & (STACK_SIZE-1); +} + +void +exec_insn (struct state *state, struct cell *cell) +{ + /* Increment cycle counters. */ + state->cell_cycle++; + cell->cycle++; + + /* State? */ + if (cell->state == state_exec) + { + int insn, error; + + next: + /* Fetch next insn. */ + if (check_exec_access (state, cell, cell->p) || + chance (access_control_failure)) + { + insn = get_soup (state, cell->frag, cell->p); + } + else + { + INC_ERRORS (state, cell); + + /* Increment PC */ + cell->p++; + + return; + } + + /* By doing this we allow the cell to use the top two bits of + * each instruction byte for its own purposes. DNA uses a similar + * technique - it can mark up basic sequences by adding its + * own arbitrary chemical markers to each base. + */ + insn &= 0x3f; + +#if TRACE + trace (cell, insn); +#endif + + if (chance (soup_fetch_failure)) + { + insn = get_rand_byte () & 0x3f; + } + + /* Increment PC */ + if (!chance (inc_pc_failure)) + { + cell->p++; + } + + /* Is this insn going to generate an error? Handle that case + * separately (don't disturb the fast path). + */ + error = chance (insn_exec_failure); + + if (!error) + { + switch (insn) + { + case 0: /* NOP0 */ + case 1: /* NOP1 */ + return; /* Ignore. */ + case 2: /* INC A */ + cell->a++; + return; + case 3: /* DEC A */ + cell->a--; + return; + case 4: /* SHL A */ + cell->a <<= 1; + return; + case 7: /* IFZ */ + if (cell->a == 0) + goto next; /* Fetch and execute next instruction. */ + /* Else skip next insn. */ + cell->p++; + return; + case 8: /* FINDB */ + if ((cell->plen = get_pattern_length (state, cell)) > 0) + { + cell->state = state_find; + cell->dir = -1; + cell->i = cell->p - 2; + cell->lim = FIND_LENGTH_LIMIT; + } + else + { + INC_ERRORS (state, cell); + cell->i = 0; + } + return; + case 9: /* FINDF */ + if ((cell->plen = get_pattern_length (state, cell)) > 0) + { + cell->state = state_find; + cell->dir = 1; + cell->i = cell->p + cell->plen + 1; + cell->lim = FIND_LENGTH_LIMIT; + } + else + { + INC_ERRORS (state, cell); + cell->i = 0; + } + return; + case 0x0a: /* MALLOC */ + if (!cell->daughter && + cell->a >= MIN_CELL_SIZE && cell->a <= MAX_CELL_SIZE) + { + struct soup_frag *frag + = soup_frag_malloc (state, cell->frag, cell->a); + if (frag) + { + cell->daughter + = cell_malloc (state, cell, frag); + /* Calculate relative address of daughter */ + cell->i + = cell->daughter->frag->base + - cell->frag->base; +#if 0 + printf ("MALLOC: dfb = %d, fb = %d, i = %d\n", + cell->daughter->frag->base, + cell->frag->base, + cell->i); +#endif + } + else + { + /* INC_ERRORS (state, cell); -- Dubious? */ + cell->i = 0; + } + } + else + { + INC_ERRORS (state, cell); + cell->i = 0; + } + return; + case 0x0b: /* DIVIDE */ + if (cell->daughter) + { + cell_divide (state, cell, cell->daughter); + cell_activate (state, cell->daughter); + cell->daughter = 0; + } + else + { + INC_ERRORS (state, cell); + cell->i = 0; + } + return; + case 0x0c: /* MOVE [I],A */ + cell->a = get_soup (state, cell->frag, cell->i); + return; + case 0x0d: /* MOVE A,[I] */ + if (check_access (state, cell, cell->i) || + chance (access_control_failure)) + { + set_soup (state, cell->frag, cell->a, cell->i); + } + else + { + INC_ERRORS (state, cell); + } + return; + case 0x0e: /* DMOVE [I],A */ + cell->a = get_soup (state, cell->frag, cell->i) << 8; + cell->a |= get_soup (state, cell->frag, cell->i+1); + return; + case 0x0f: /* DMOVE A,[I] */ + if ((check_access (state, cell, cell->i) && + check_access (state, cell, cell->i+1)) || + chance (access_control_failure)) + { + set_soup (state, cell->frag, cell->a >> 8, cell->i); + set_soup (state, cell->frag, cell->a & 0xff, cell->i+1); + } + else + { + INC_ERRORS (state, cell); + } + return; + case 0x10: /* XOR A,A (ie. ZERO A) */ + cell->a = 0; return; + case 0x11: /* XOR B,A */ + cell->a ^= cell->b; return; + case 0x12: /* XOR I,A */ + cell->a ^= cell->i; return; + case 0x13: /* XOR P,A */ + cell->a ^= cell->p; return; + case 0x14: /* XOR A,B */ + cell->b ^= cell->a; return; + case 0x15: /* XOR B,B (ie. ZERO B) */ + cell->b = 0; return; + case 0x16: /* XOR I,B */ + cell->b ^= cell->i; return; + case 0x17: /* XOR P,B */ + cell->b ^= cell->p; return; + case 0x18: /* XOR A,I */ + cell->i ^= cell->a; return; + case 0x19: /* XOR B,I */ + cell->i ^= cell->b; return; + case 0x1a: /* XOR I,I (ie. ZERO I) */ + cell->i = 0; return; + case 0x1b: /* XOR P,I */ + cell->i ^= cell->p; return; + /* Surely these next three instructions will never be used ... */ + case 0x1c: /* XOR A,P */ + cell->p ^= cell->a; return; + case 0x1d: /* XOR B,P */ + cell->p ^= cell->b; return; + case 0x1e: /* XOR I,P */ + cell->p ^= cell->i; return; + case 0x1f: /* XOR P,P (ie. ZERO P) */ + cell->p = 0; return; + case 0x20: /* PUSH A */ + push (cell, cell->a); + return; + case 0x21: /* PUSH B */ + push (cell, cell->b); + return; + case 0x22: /* PUSH I */ + push (cell, cell->i); + return; + case 0x23: /* PUSH P */ + push (cell, cell->p); + return; + case 0x24: /* POP A */ + pop (cell, &cell->a); + return; + case 0x25: /* POP B */ + pop (cell, &cell->b); + return; + case 0x26: /* POP I */ + pop (cell, &cell->i); + return; + case 0x27: /* POP P */ + pop (cell, &cell->p); + return; + + default: /* Unknown instruction. */ + INC_ERRORS (state, cell); + return; + } + } + else + { + /* Slow path: insn will execute in error. */ + switch (insn) + { + case 2: /* INC A */ + if (chance (2)) + cell->a += 2; + return; + case 3: /* DEC A */ + if (chance (2)) + cell->a -= 2; + return; + case 4: /* SHL A */ + if (chance (2)) + cell->a <<= 2; + return; + case 7: /* IFZ */ + if (chance (2)) + goto next; /* Fetch and execute next instruction. */ + /* Else skip next insn. */ + cell->p++; + return; + case 8: /* FINDB */ + if (chance (2)) + cell->i = 0; + return; + case 9: /* FINDF */ + if (chance (2)) + cell->i = 0; + return; + case 0x0c: /* MOVE [I],A */ + cell->a = get_soup (state, cell->frag, cell->i); + if (chance (2)) + cell->a++; + else + cell->a--; + return; + case 0x0d: /* MOVE A,[I] */ + { + int i = chance (4); + switch (i) + { + case 0: + set_soup (state, cell->frag, cell->a+1, cell->i); + return; + case 1: + set_soup (state, cell->frag, cell->a-1, cell->i); + return; + case 2: + set_soup (state, cell->frag, cell->a, cell->i+1); + return; + case 3: + set_soup (state, cell->frag, cell->a, cell->i-1); + return; + } + return; + } + case 0x0e: /* DMOVE [I],A */ + cell->a = get_soup (state, cell->frag, cell->i) << 8; + cell->a |= get_soup (state, cell->frag, cell->i+1); + if (chance (2)) + cell->a++; + else + cell->a--; + return; + case 0x0f: /* DMOVE A,[I] */ + { + int i = chance (4); + switch (i) + { + case 0: + set_soup (state, cell->frag, (cell->a+1) >> 8, cell->i); + set_soup (state, cell->frag, (cell->a+1) & 0xFF, cell->i+1); + return; + case 1: + set_soup (state, cell->frag, (cell->a-1) >> 8, cell->i); + set_soup (state, cell->frag, (cell->a-1) & 0xFF, cell->i+1); + return; + case 2: + set_soup (state, cell->frag, cell->a >> 8, cell->i+1); + set_soup (state, cell->frag, cell->a & 0xFF, cell->i+2); + return; + case 3: + set_soup (state, cell->frag, cell->a >> 8, cell->i-1); + set_soup (state, cell->frag, cell->a & 0xFF, cell->i); + return; + } + return; + } + case 0x10: /* XOR ... */ + return; + case 0x11: + cell->a = cell->b; return; + case 0x12: + cell->a = cell->i; return; + case 0x13: + cell->a = cell->p; return; + case 0x14: + cell->b = cell->a; return; + case 0x15: + return; + case 0x16: + cell->b = cell->i; return; + case 0x17: + cell->b = cell->p; return; + case 0x18: + cell->i = cell->a; return; + case 0x19: + cell->i = cell->b; return; + case 0x1a: + return; + case 0x1b: + cell->i = cell->p; return; + case 0x1c: + cell->p = cell->a; return; + case 0x1d: + cell->p = cell->b; return; + case 0x1e: + cell->p = cell->i; return; + case 0x1f: + return; + } + } + } + else /* cell->state == state_find */ + { + /* During finds, + * cell->p == address of pattern complement to match + * cell->plen == length of pattern + * cell->i == current address of search + * cell->dir == direction of search (-1 or 1) + * cell->lim == number of steps before we give up + */ + int i; + +#if TRACE + trace (cell, -1); +#endif + + for (i = 0; i < cell->plen; ++i) + { + int pat = get_soup (state, cell->frag, cell->p+i); + int mat = get_soup (state, cell->frag, cell->i+i); + if (pat > 1 || mat > 1 || pat == mat) + { + /* Not matched: continue searching. */ + cell->i += cell->dir; + cell->lim--; + if (cell->lim == 0) + { + /* Give up. */ + cell->i = 0; + INC_ERRORS (state, cell); + cell->state = state_exec; + cell->p += cell->plen; + return; + } + return; + } + } /* for */ + + /* Pattern matched! */ + cell->p += cell->plen; + cell->state = state_exec; + return; + } +} + +#if TRACE +static void +trace (const struct cell *cell, int insn) +{ + if (cell->state == state_exec) + { + printf ("x %p A:%d B:%d I:%d P:%d St:[%d %d %d..] e:%d [%p] ", + cell, cell->a, cell->b, cell->i, cell->p, + cell->stack[cell->sp], + cell->stack[(cell->sp-1) & (STACK_SIZE-1)], + cell->stack[(cell->sp-2) & (STACK_SIZE-1)], + cell->errors, + cell->daughter); + switch (insn) + { + case 0: printf ("NOP0"); break; + case 1: printf ("NOP1"); break; + case 2: printf ("INC A"); break; + case 3: printf ("DEC A"); break; + case 4: printf ("SHL A"); break; + case 7: printf ("IFZ"); break; + case 8: printf ("FINDB"); break; + case 9: printf ("FINDF"); break; + case 10: printf ("MALLOC"); break; + case 11: printf ("DIVIDE"); break; + case 12: printf ("MOVE [I],A"); break; + case 13: printf ("MOVE A,[I]"); break; + case 14: printf ("DMOVE [I],A"); break; + case 15: printf ("DMOVE A,[I]"); break; + case 16: case 17: case 18: case 19: + case 20: case 21: case 22: case 23: + case 24: case 25: case 26: case 27: + case 28: case 29: case 30: case 31: + printf ("XOR %c,%c", "ABIP"[insn&3], "ABIP"[(insn>>2)&3]); break; + case 32: case 33: case 34: case 35: + printf ("PUSH %c", "ABIP"[insn&3]); break; + case 36: case 37: case 38: case 39: + printf ("POP %c", "ABIP"[insn&3]); break; + default: printf ("unknown %d", insn); break; + } + printf ("\n"); + } + else + { + printf ("f %p I:%d P:%d dir:%d plen:%d lim:%d\n", + cell, cell->i, cell->p, cell->dir, cell->plen, cell->lim); + } +} +#endif diff --git a/god.dla b/god.dla new file mode 100644 index 0000000..467538e --- /dev/null +++ b/god.dla @@ -0,0 +1,90 @@ +;; GOD CELL +;; BY RICHARD W.M. JONES + +00001: ; Marks beginning of the cell. + + JMPF ~00011 ; Jump to start of the cell code + ; proper. + +00010: ; Marks start of local variables. + DW 4 ; Local variable storage. + + ; This is the main cell program. + +00011: ; Marks the start of the cell code. + + ; When debugging, use this canard to detect stack underflows. + ;MOVE 65535,A + ;PUSH A + + FINDB ~00010 ; Find beginning of local variables. + MOVE I,A ; Add length of label. + ADD 5,A + MOVE A,B ; Initialize base register. + FINDB ~00001 ; Find beginning address of cell. + MOVE I,A + STORE A,0 ; Save it for later. + FINDF ~01111 ; Find end address of cell. + MOVE I,A + ADD 5,A ; Add length of final label. + STORE A,1 ; Save it for later. + + CALLF ~00100 ; Call subroutine to subtract + ; var 0 from var 1 and store in var 2. + + LOAD 2,A ; Load the computed length. + MALLOC ; Allocate memory for the daughter. + MOVE I,A + JMPZB ~00011 ; If allocation failed, start again. + STORE A,3 ; Store the daughter's address in 3. + + CALLF ~00110 ; Call subroutine to do the copy. + + DIVIDE ; Break off the daughter cell. + + JMPB ~00011 ; Repeat forever! + + ; This subroutine subtracts var 0 from var 1 and stores the + ; resulting value in var 2. + +00100: + LOAD 1,A ; Copy var 1 into var 2 + STORE A,2 + LOAD 0,A ; A <- amount to subtract +00101: JMPZF ~01001 ; Loop until A == 0 + PUSH A + LOAD 2,A ; Subtract 1 from var 2. + DEC A + STORE A,2 + POP A + DEC A + JMPB ~00101 +01001: RET 5 + + ; This subroutine copies var 2 bytes from [var 0] to [var 3] (ie. + ; from the mother to the daughter). + +00110: + LOAD 2,A ; Number of bytes to copy. +00111: JMPZF ~01000 ; Leave loop when A == 0. + PUSH A + LOAD 0,A ; Get source address. + MOVE A,I + MOVE [I],A ; Get item to copy from source. + PUSH A + LOAD 3,A ; Get destination address. + MOVE A,I + POP A + MOVE A,[I] ; Store item at destination addr. + LOAD 0,A ; Increment source address. + INC A + STORE A,0 + LOAD 3,A ; Increment destination address. + INC A + STORE A,3 + POP A + DEC A + JMPB ~00111 +01000: RET 5 + +01111: ; Marks end of the cell. diff --git a/god.dlo b/god.dlo new file mode 100644 index 0000000..da9c6a2 --- /dev/null +++ b/god.dlo @@ -0,0 +1,56 @@ +00000000010901010100002227 +0000000100FFFFFFFFFFFFFFFF +000000010108 +01010100012224 +0202020202 +2025 +08 +01010101002224 +222021242026240F26 +09 +01000000002224 +0202020202 +2220212402022026240F26 +230901010001012227 +2221240202020220260E26 +0A +2224 +08010101000022072726 +222021240202020202022026240F26 +230901010000012227 +0B +0801010100002227 +0000010000222124020220260E26 +22202124020202022026240F26 +22212420260E26 +000001000109010001010022072726 +20 +2221240202020220260E26 +03 +22202124020202022026240F26 +24 +03 +0801010001002227 +00010000012402020202020202022027 +00000101002221240202020220260E26 +000001010109010001010122072726 +20 +22212420260E26 +2026 +0C +20 +22212402020202020220260E26 +2026 +24 +0D +22212420260E26 +02 +222021242026240F26 +22212402020202020220260E26 +02 +222021240202020202022026240F26 +24 +03 +0801010000002227 +00010000002402020202020202022027 +0001010101 diff --git a/image.c b/image.c new file mode 100644 index 0000000..ed632fd --- /dev/null +++ b/image.c @@ -0,0 +1,106 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: image.c,v 1.2 2002/04/05 16:47:12 rich Exp $ + */ + +#include "config.h" + +#include +#include + +#include "image.h" +#include "state.h" +#include "cell.h" +#include "soup.h" + +#define FILE_SAVE_VERSION 1 + +static void global_state_save (struct state *state, FILE *fp); +static void global_state_load (struct state *state, FILE *fp); + +struct state * +image_load (const char *filename, int _soup_size, int thread_num) +{ + FILE *fp; + struct state *state; + + fp = fopen (filename, "r"); + if (fp == 0) { perror (filename); return 0; } + + state = state_malloc (_soup_size, thread_num); + + global_state_load (state, fp); + cell_state_load (state, fp); + soup_state_load (state, fp); + + fclose (fp); + + return state; +} + +int +image_save (struct state *state, const char *filename) +{ + FILE *fp; + + fp = fopen (filename, "w"); + if (fp == 0) { perror (filename); return -1; } + + global_state_save (state, fp); + cell_state_save (state, fp); + soup_state_save (state, fp); + + fclose (fp); + + return 0; +} + +static void +global_state_save (struct state *state, FILE *fp) +{ + int version = FILE_SAVE_VERSION; + + fwrite (&version, sizeof version, 1, fp); + fwrite (&state->cell_cycle, sizeof state->cell_cycle, 1, fp); +} + +static void +global_state_load (struct state *state, FILE *fp) +{ + int version; + + if (fread (&version, sizeof version, 1, fp) != 1) + { + fprintf (stderr, "error in global state\n"); + abort (); + } + if (version != FILE_SAVE_VERSION) + { + fprintf (stderr, "soup image version numbers do not match\n"); + abort (); + } + + if (fread (&state->cell_cycle, sizeof state->cell_cycle, 1, fp) != 1) + { + fprintf (stderr, "error in global state\n"); + abort (); + } + + if (verbose) printf ("Total number of cycles executed so far: %LuB\n", + state->cell_cycle / 1000000000); +} diff --git a/image.h b/image.h new file mode 100644 index 0000000..d127a6b --- /dev/null +++ b/image.h @@ -0,0 +1,30 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: image.h,v 1.1 2002/04/05 14:40:27 rich Exp $ + */ + +#ifndef image_h +#define image_h + +#include "state.h" + +extern struct state *image_load (const char *filename, int _soup_size, + int thread_num); +extern int image_save (struct state *state, const char *filename); + +#endif /* image_h */ diff --git a/index.html.in b/index.html.in new file mode 100644 index 0000000..9b31ff0 --- /dev/null +++ b/index.html.in @@ -0,0 +1,111 @@ + + + + + Distributed Artificial Life + + + +

Distributed Artificial Life

+ +

+ DLIFE is a distributed version of Tom S. Ray's Tierra + artificial life program. Note that the machine language used is + similar to but not compatible with Tierra. Tom Ray talks about + his work (as far as I know, never completed) to create a ``Digital + Reserve''. The DLIFE project is a development of this. +

+ +

+ In other words, it's an alternative to the tedious process + of cracking RC5 keys + or searching + for aliens. You've got a supercomputer on your desk, + let's go and create some life ... +

+ +

News

+ +

Fri Apr 5 23:03:27 BST 2002

+ +

+ Version 1.0.0: Various fixes for Red Hat Linux 7.2. +

+ +

Mon Oct 16 23:11:13 BST 2000

+ +

+ Version 0.0.16: Added another patch from Falk + Hueffner which improves the Debian package + handling. +

+ +

Sat Oct 14 15:44:27 BST 2000

+ +

+ Version 0.0.15: Debian package (thanks to Falk Hueffner). + Client and soup processes now log status information to syslog. +

+ +

Download

+ +

+ All software is distributed under the terms of the + GNU General Public License (GPL). +

+ +

+ The latest version is @VERSION@, released @RELEASEDATE@. +

+ + + + + + + + + + + + + + + + + + + + + + +
Source code for client and server dlife-@VERSION@.tar.gz
Client: Binary RPM (for Red Hat, i686) dlife-@VERSION@-1.i686.rpm
Server: Binary RPM (for Red Hat, i686) dlife-server-@VERSION@-1.i686.rpm
Source RPM dlife-server-@VERSION@-1.src.rpm
Perl RPMs Various Perl RPMs which you may require ...
+ +

Patches from previous versions ...

+

Previous versions ...

+ +

Documentation

+ +
    +
  • DLIFE machine language reference
    + Documents the machine language implemented in the DLIFE + VM, the underlying philosophy, and how it differs from + the original Tierra machine language. +
  • DLIFE distributed architecture reference +
    + Documents the distributed architecture of DLIFE, how + the VM runs, how cells get distributed between soups, + and how the C VM code and Perl network code interact. +
+ +
+
rich@annexia.org
+ + +Last modified: Mon Oct 16 23:11:50 BST 2000 + + + diff --git a/install-sh b/install-sh new file mode 120000 index 0000000..e534836 --- /dev/null +++ b/install-sh @@ -0,0 +1 @@ +/usr/share/automake-1.4/install-sh \ No newline at end of file diff --git a/load.c b/load.c new file mode 100644 index 0000000..68b9128 --- /dev/null +++ b/load.c @@ -0,0 +1,116 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: load.c,v 1.2 2002/04/05 16:47:12 rich Exp $ + */ + +#include "config.h" + +#include +#include +#include + +#include "types.h" +#include "load.h" +#include "cell.h" +#include "soup.h" +#include "state.h" + +struct cell * +load_cell (struct state *state, const char *filename) +{ + FILE *fp; + int allocated = 0; + int len = 0; + char line[256]; + byte_t *code = 0; + int n = 0, i, c = 0; + struct cell *cell; + struct soup_frag *frag; + + fp = fopen (filename, "r"); + if (fp == 0) { perror (filename); return 0; } + + while (fgets (line, sizeof line, fp) != 0 && len < MAX_CELL_SIZE) + { + for (i = 0; i < strlen (line); ++i) + { + if (line[i] >= '0' && line[i] <= '9') + { + n *= 16; + n += line[i] - '0'; + c++; + } + else if (line[i] >= 'a' && line[i] <= 'f') + { + n *= 16; + n += line[i] - 'a' + 10; + c++; + } + else if (line[i] >= 'A' && line[i] <= 'F') + { + n *= 16; + n += line[i] - 'A' + 10; + c++; + } + if (c == 2) + { + if (allocated - len <= 0) + { + code = realloc (code, allocated += 256); + if (code == 0) { perror ("realloc"); abort (); } + } + code[len++] = n; + n = c = 0; + } + } + } + + if (c != 0) + { + fprintf (stderr, "%s: error in input file\n", filename); + fclose (fp); + free (code); + return 0; + } + + fclose (fp); + + /* Refuse any cells which are too small or too large. */ + if (len < MIN_CELL_SIZE || len > MAX_CELL_SIZE) + { + fprintf (stderr, "%s: cell is too small or too large (len = %d)\n", + filename, len); + free (code); + return 0; + } + + /* Allocate soup fragment. */ + frag = soup_frag_malloc (state, 0, len); + if (frag == 0) { free (code); return 0; } + + /* Allocate cell. */ + cell = cell_malloc (state, 0, frag); + if (cell == 0) { free (code); return 0; } + + /* Populate cell. */ + for (i = 0; i < len; ++i) + set_soup (state, cell->frag, code[i], i); + free (code); + + return cell; +} diff --git a/load.h b/load.h new file mode 100644 index 0000000..9343cf3 --- /dev/null +++ b/load.h @@ -0,0 +1,29 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: load.h,v 1.1 2002/04/05 14:40:27 rich Exp $ + */ + +#ifndef load_h +#define load_h + +#include "config.h" +#include "state.h" + +extern struct cell *load_cell (struct state *state, const char *filename); + +#endif /* load_h */ diff --git a/machineref.html b/machineref.html new file mode 100644 index 0000000..2ed3d98 --- /dev/null +++ b/machineref.html @@ -0,0 +1,746 @@ + + + + DLIFE machine language reference + + + +

DLIFE machine language reference

+ +

General overview

+ +

+ I'm going to assume that you're mostly familiar + with Tierra, + but I'll also give you a short introduction. +

+ +

+ In DLIFE/Tierra, life forms consist of small + machine language programs called ``cells''. + Each cell has its own program counter and hence + its own thread of execution, and runs independently + of any other cell. Cells live in a virtual machine + (VM) called the ``soup''. The soup is just a big + piece of byte-addressed memory, 128 Kbytes in size + by default. +

+ +

+ The soup contains an interpreter which interprets + the machine language. For DLIFE cells, the soup + is their entire universe. They cannot address or + access anything outside their own soup. (Although + they can occasionally jump from one soup to another + -- but more of that later). +

+ +

+ All the cells sharing the soup are run timesliced + in a simple round-robin scheme, and hence each + cell will get roughly the same amount of actual CPU + dedicated to it. +

+ +

+ The cell machine language is not 8086 assembler. In + fact, it's a special purpose machine language written + just to run cells. It has some similarities with + more traditional machine languages -- for example, + registers, indirect addressing, jumps, a stack, + and so on -- but also some strange features that + you wouldn't expect to find in a real machine + language. The most important feature of the + language is termed (in a term coined by Tom + Ray) its ``non-brittleness''. This means that + the language is robust against small corruptions, + changes, and the insertion or deletion of a few + bytes here and there. In a real machine language, + inserting a few bytes into a piece of code requires + that you relink the code so that all jump and call + target addresses change. If you didn't relink the code, + then the insertion would be fatal -- the code wouldn't + function at all. Real machine languages are said to + be ``brittle''. In the DLIFE machine language, insertions + and deletions are tolerated -- the code will continue to + work much as before. The main way in which this works + is that absolute addresses have been replaced by + explicit labels in the code: +

+ +
+  code
+  : :
+  code
+  label 123
+  code
+  : :   <---
+  code
+  jump to label 123
+  code
+  : :
+  code
+
+ +

+ Suppose in the example above that an accidental + insertion or deletion occurs at the point marked by the arrow. + The chances are that the code will continue to work, + because the ``jump'' command will still be able to + find and jump to the correct label. +

+ +

+ Another important and unusual feature of the machine + language is that it allows cells to reproduce. Through + the use of the MALLOC and DIVIDE + instructions, a cell may produce a daughter cell, + populate it with code, and then divide (set it running + as an independent cell). +

+ +

+ The soup interpreter is error-prone. Most instructions + will run as intended, but occasionally instructions + fail in certain ways. For example, an instruction to + increment the accumulator might, one in a hundred thousand times, + increment the accumulator twice, or even not at + all. The soup memory is also error-prone. So-called + cosmic rays hit the soup very occasionally, flipping + bits at random. By these means, cells may occasionally + mutate. Note that because the machine language is + very deliberately chosen to be non-brittle, mutations + often result in cells which still work, but perhaps + work in slightly different (better?) ways. Hence + cells evolve. +

+ +

+ There is one initial cell, which was written by hand. This + cell is called the ``god cell'' (although perhaps Adam + or Eve might have been a better biblical parallel). This + cell simply copies itself repeatedly. +

+ +

+ Cells which execute instructions incorrectly (for + example, they do not fill the accumulator register + with a suitable value before calling MALLOC) + accumulate errors. As the soup becomes more and more + full, a special process called the ``grim reaper'' + is invoked. The grim reaper kills off the cells + with the largest error count until the soup pressure + is eased. +

+ +

+ The DLIFE model is one of pure natural selection. There + are no artificial pressures placed on cells to become, + for example, good at executing some particular algorithm. + Instead, cells compete simply for space in the soup + and time on the virtual CPU. +

+ +

Cell virtual machine

+ +

+ The cell VM consists of 4 registers, some local + storage, a stack and stack pointer, an error counter + and possibly an attached daughter cell. +

+ +

Registers

+ +

+ The 4 visible registers are: +

+ + + + + + + + + + + + + + + + + +
Register Purpose
A The accumulator, for mathematical + operations and general purpose use.
B Base address, for addressing local variables.
I Index address.
P Program counter.
+ +

+ All registers are 16 bit signed integers, storing + any value between -32768 and 32767 inclusive. +

+ +

+ All addresses are stored relative to the start + address of the cell. Hence if P is set to zero, + then execution jumps to the beginning of the cell's + code. +

+ +

+ When a cell is created, all registers are initialized + to zero. +

+ +

Local storage

+ +

+ The cell has a fragment of soup memory. Because addresses + are relative, to the cell the memory appears to stretch from + address 0 to address N-1, where N is the total number + of bytes allocated to the cell by her mother's call + to MALLOC. It is not possible for + the cell to find out the value of N (we assume that + the mother allocated enough memory for the cell). +

+ +

+ A cell may store code or data at any memory address + within itself. There is no distinction made in the + VM between code and data. +

+ +

+ A cell may not write to memory outside the range 0 to N-1. + Doing so will incur an error. Cells may, however, read + any memory outside this range. +

+ +

+ After calling MALLOC, the I register is + initialized with the start address of the daughter + cell. Between the MALLOC and the next call + to DIVIDE, the cell may additionally write + to addresses I through I + A - 1, in order to initialize + the daughter. +

+ +

Stack

+ +

+ The cell has a stack of 16 words. Each stack entry is + a 16 bit signed integer. +

+ +

+ A stack pointer stores the current position in the + stack. +

+ +

+ The stack can only be accessed through one of the PUSH + or POP instructions. PUSH x (where ``x'' is + the name of a register) increments the value of the + stack pointer and copies the value in register x onto + the stack at the position addressed by the stack pointer. + POP x copies the value on the stack addressed + by the stack pointer into register x and decrements the + value of the stack pointer. +

+ +

+ The stack is circular, in that pushing more than 16 numbers + onto the stack causes the stack to wrap around and overwrite + the top entry. Thus it is not possible to underflow or + overflow the stack. +

+ +

+ The stack pointer register is not visible to the cell + VM. In other words, the cell cannot directly read or write + to the stack pointer (except implicitly through use of + the PUSH or POP instructions). Because + of this, it is not possible for the cell to tell if the + stack is implemented as grows-down or grows-up, nor + whether the implementation pushes first and changes the + stack pointer second or vice versa. +

+ +

+ When the cell is created, all stack entries and the stack + pointer are initialized to zero. +

+ +

Error counter

+ +

+ The error counter starts off at zero, and is incremented + by one every time the cell makes a mistake when + executing an instruction. Typical mistakes are: +

+ +
    +
  • Incorrectly initializing the A register before + calling MALLOC. +
  • Not calling MALLOC before calling DIVIDE. +
  • Not calling DIVIDE before calling MALLOC. +
  • Executing FINDF or FINDB and not + finding a matching label. +
+ +

Basic instruction set

+ +

+ The basic instruction set consists of just 17 commands + encoded in just 38 different numeric values. +

+ +

+ Each instruction is encoded in a single byte. +

+ +

+ Two instructions, FINDB and FINDF + might be considered to be multi-byte instructions. + See the description below for details. +

+ +

+ There is one instruction prefix, IFZ, but + in the discussion below, we will just consider it + as if it was a single byte instruction (which, in + fact, it is). +

+ +

+ The VM makes no distinction between code and data. + Any byte which is addressable as part of the mother + cell can be considered to be either executable + code or a data byte (or both). +

+ +

+ Instructions are encoded into soup bytes as follows: +

+ +
+ Most                              Least
+ significant                 significant
+ bit                                 bit
++----+----+----+----+----+----+----+----+
+|    |    |    |    |    |    |    |    |
+| 7  | 6  | 5  | 4  | 3  | 2  | 1  | 0  |
+|    |    |    |    |    |    |    |    |
++----+----+----+----+----+----+----+----+
+ \_______/ \___________________________/
+     |                   |
+  Ignored       Instruction encoding
+             (values 0-4,7-39 correspond to
+              instructions, values 40-63
+              are unknown and result in
+              cell errors)
+
+ +

+ The lower 6 bits are interpreted as follows: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Dec Hex Bin Mnemonic Meaning
0 00 00 0000 NOP0 No-op. This instruction does nothing when executed + but is used as a pattern matching label by FINDB + and FINDF.
1 01 00 0001 NOP1 No-op. This instruction does nothing when executed + but is used as a pattern matching label by FINDB + and FINDF.
2 02 00 0010 INC A A <- A + 1
3 03 00 0011 DEC A A <- A - 1
4 04 00 0100 SHL A A <- A << 1
7 07 00 0111 IFZ IFZ is normally used as an instruction + prefix, ie. IFZ <instruction>. + If A == 0, execute the next instruction, + otherwise skip the next instruction.
8 08 00 1000 FINDB FINDB should be followed by a pattern + (a series of one or more NOP0 and NOP1 bytes). The + FINDB instruction searches backwards + from the current program counter until it finds + the inverse pattern of NOP0 and NOP1 bytes. + It returns the relative address of the found pattern + in register I. If the pattern is not found, it + sets I == 0. +
9 09 00 1001 FINDF FINDF should be followed by a pattern + (a series of one or more NOP0 and NOP1 bytes). The + FINDF instruction searches forwards + from the current program counter until it finds + the inverse pattern of NOP0 and NOP1 bytes. + It returns the relative address of the found pattern + in register I. If the pattern is not found, it + sets I <- 0. +
10 0A 00 1010 MALLOC MALLOC allocates a daughter + cell of size A bytes. It returns the address + of the daughter cell in register I, or if the + memory could not be allocated, it sets I <- 0. + Only one daughter cell may be allocated at a + time. Therefore, calling MALLOC twice + without calling DIVIDE in between is an + error. Register A must be between 10 and 512. +
11 0B 00 1011 DIVIDE DIVIDE splits off the current daughter + cell and starts it running as a fully independent + cell. The daughter cell must first have been allocated + by MALLOC and populated with code, so + calling DIVIDE twice without calling + MALLOC in between is an error. +
12 0C 00 1100 MOVE [I],A Load the unsigned byte at relative address I into + register A. +
13 0D 00 1101 MOVE A,[I] Store the value of register A in the soup byte + at relative address I. If A is less than 0 or + greater than 255 then the effects are undefined. + If I lies outside the boundaries of the mother + or daughter cells, then this is a cell error. +
14 0E 00 1110 DMOVE [I],A Load the signed word (two bytes) at relative address I + into register A. The VM is big endian (Motorola ordering). +
15 0F 00 1111 DMOVE A,[I] Store the value of register A in the soup + bytes at relative address I and I+1. If (I, I+1) + lies outside the boundaries of the mother or + daughter cells, then this is a cell error. + The VM is big endian (Motorola ordering). +
16-31 10-1F 01 r2r1 XOR <reg1>,<reg2> <reg2> <- <reg1> XOR <reg2> + for any registers in A (00), B (01), I (10) or P (11). +
32-35 20-23 10 00rr PUSH <reg> Push the register onto the stack for any + registers in A (00), B (01), I (10) or P (11). +
36-39 24-27 10 01rr POP <reg> Pop the top of the stack into the register for + any registers in A (00), B (01), I (10) or P (11). +
+ +

+ Note that instruction encodings 5, 6 and 40-63 are + not used. Attempting to execute one of these unknown + instructions results in a cell error. +

+ +

Instruction set timings

+ +

+ This table shows the number of (virtual) CPU cycles + taken to execute each instruction. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Instruction Cycles Notes
NOP0 1
NOP1 1
INC A 1
DEC A 1
SHL A 1
IFZ 1
FINDB 1 + n ``n'' is the distance between the current + program counter and the start of the matched + pattern.
FINDF 1 + n ``n'' is the distance between the current + program counter and the start of the matched + pattern.
MALLOC 1
DIVIDE 1
MOVE [I],A 1
MOVE A,[I] 1
DMOVE [I],A 1
DMOVE A,[I] 1
XOR <reg1>,<reg2> 1
PUSH <reg> 1
POP <reg> 1
+ +

Instruction set macros

+ +

+ The basic instruction set is augmented with macros + which allow common programming paradigms to be + written. Macros are just a short-hand used in + the assembler / disassembler, and are not implemented + in any way by the VM. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Macro Expands to Meaning Side effects?
Basic register operations ...
MOVE <reg1>,<reg2> PUSH <reg1>
POP <reg2>
Move the contents of register 1 into register 2. None.
SWAP <reg1>,<reg2> XOR <reg1>,<reg2>
+ XOR <reg2>,<reg1>
+ XOR <reg1>,<reg2>
+ XOR <reg2>,<reg1>
This has the effect of swapping the contents of + registers 1 and 2. None.
ZERO <reg> XOR <reg>,<reg> A <- 0 None.
ADD <n>, A INC A repeated n times. This is only + really suitable for small values of n. A <- A + n None.
MOVE <n>, A ZERO A followed by a series of + SHL A and INC A operations + required to initialize A to n. (n >= 0) A <- n None.
Access local (word-sized) variables, relative + to the base address register B ...
LOAD <n>, A PUSH I
MOVE B,A
ADD n*2,A
MOVE A,I
+ DMOVE [I],A
POP I
Load variable number n into register A. Destroys contents of I register.
STORE A,<n> PUSH I
PUSH A
MOVE B,A
ADD n*2,A
MOVE A,I
+ POP A
DMOVE A,[I]
POP I
Store register A in variable number n. Destroys contents of I register.
Jumps and subroutines ...
JMP I PUSH I
POP P
Jump to address I. None.
JMPF <pattern> FINDF <pattern>
PUSH I
POP P
Jump forwards to pattern. Destroys contents of I register.
JMPB <pattern> FINDB <pattern>
PUSH I
POP P
Jump backwards to pattern. Destroys contents of I register.
JMPZF <pattern> FINDF <pattern>
PUSH I
IFZ POP P
+ POP I
If A == 0, jump forwards to pattern. Destroys contents of I register.
JMPZB <pattern> FINDB <pattern>
PUSH I
IFZ POP P
+ POP I
If A == 0, jump backwards to pattern. Destroys contents of I register.
CALLF <pattern> PUSH P
FINDF <pattern>
PUSH I
POP P
Call forwards to a subroutine at pattern. The current + address is saved on the stack. Destroys contents of I register.
CALLB <pattern> PUSH P
FINDB <pattern>
PUSH I
POP P
Call backwards to a subroutine at pattern. The current + address is saved on the stack. Destroys contents of I register.
RET <n> POP A
ADD n+3,A
MOVE A,P
Return from subroutine. n is the length of the + pattern in the corresponding CALLF/CALLB + instruction. The return address should be the top + address on the stack. Destroys contents of A register.
Assembler directives ...
DB <n>   Define n bytes of scratch space. The scratch + space is initialized with 0xFF bytes (not + with zero bytes, since those clash with pattern symbols). None.
+ +

Patterns

+ +

+ The assembler recognizes patterns and writes out + a series of NOP0 and NOP1 bytes. +

+ + + + + + + + + + + + + + + + + + + + + +
Mnemonic Expands to
<pattern>: Each 0 and 1 in the pattern is translated into + a NOP0 and NOP1 on output.
~<pattern>: Each 0 and 1 in the pattern is translated into + a NOP1 and NOP0 on output (note the inversion).
instruction <pattern>: Each 0 and 1 in the pattern is translated into + a NOP0 and NOP1 on output.
instruction ~<pattern>: Each 0 and 1 in the pattern is translated into + a NOP1 and NOP0 on output (note the inversion).
+ +

+ Since the FINDB and FINDF patterns + search for the inverse of a pattern, a typical + instruction sequence will look like this: +

+ +
+0011:
+  ; : :
+  ; : :
+
+  FINDB ~0011
+  ; I contains address of 0011 pattern.
+
+ +
+
Richard Jones
+ + +Last modified: Sat Oct 7 13:49:42 BST 2000 + + + diff --git a/main.c b/main.c new file mode 100644 index 0000000..8122d7e --- /dev/null +++ b/main.c @@ -0,0 +1,483 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: main.c,v 1.3 2002/12/11 17:16:21 rich Exp $ + */ + +#include "config.h" + +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_PWD_H +#include +#endif + +#ifdef HAVE_GRP_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_SYSLOG_H +#include +#endif + +#include "cell.h" +#include "soup.h" +#include "load.h" +#include "params.h" +#include "random.h" +#include "state.h" +#include "image.h" + +unsigned soup_fetch_failure = 1000000; +unsigned inc_pc_failure = 1000000; +unsigned insn_exec_failure = 1000000; +unsigned access_control_failure = 10; +unsigned cell_initialization_failure = 1000000; +int reaper_invoke_threshold = 80; +int reaper_reap_threshold = 79; +int save_period = 5; +int outgoing_period = 10; +int incoming_period = 60; +int info_period = 60; +int max_cells_incoming_per_pass = 4; + +int verbose = 0; + +static int soup_size = 128*1024; /* Read from configuration file. */ + +static const char *conf_file = CONFDIR "/soup.conf"; +static const char *save_dir = SPOOLDIR; + +static void parse_args (int argc, char *argv[]); +static void read_config_file (void); +static int detect_nr_cpus (void); + +int +main (int argc, char *argv[]) +{ + char filename[256]; + int nr_cpus, i; + + /* Parse the command line. */ + parse_args (argc, argv); + + /* Read the configuration file. */ + read_config_file (); + + /* Initialize stuff. */ + random_init (); + +#ifdef HAVE_OPENLOG + /* Open connection to syslog. */ + openlog ("dlife_soup", LOG_PID, LOG_DAEMON); +#endif + + /* Find out how many processors are available. */ + nr_cpus = detect_nr_cpus (); + + /* Find existing saves directory. If there is a soup image in there, + * then we will load it. Otherwise we will start with the god cell. + */ + if (chdir (save_dir) < 0) + { + perror (save_dir); + exit (1); + } + +#ifdef HAVE_NICE + /* Reduce our priority down to the minimum. */ + nice (64); +#endif + +#if defined(HAVE_GETUID) && defined(HAVE_SETUID) && defined(HAVE_SETGID) && defined(HAVE_GETPWNAM) && defined(HAVE_INITGROUPS) + /* If we are running as root, change to user dlife. */ + if (getuid () == 0) + { + struct passwd *pw = getpwnam ("dlife"); + + if (pw) + { + initgroups ("dlife", pw->pw_gid); + setgid (pw->pw_gid); + setuid (pw->pw_uid); + } + else + { + fprintf (stderr, "cannot change to user/group dlife"); + } + } +#endif + +#ifdef HAVE_SYSLOG + syslog (LOG_INFO, + "version " VERSION " starting [conf=" + CONFDIR ", spool=" SPOOLDIR ", cpus=%d]", nr_cpus); +#endif + + /* Fork once for each processor. */ + for (i = 0; i < nr_cpus; ++i) + { + int pid; + + pid = fork (); + if (pid < 0) + { + perror ("fork"); + abort (); + } + + if (pid == 0) + { + /* This is the child process. */ + struct state *cpu_state; + + /* Try to load the previous soup image. If the soup image + * cannot be found, then instead load the god cell. + */ + sprintf (filename, "saved/soup%d.img", i); + + cpu_state = image_load (filename, soup_size, i); + + if (cpu_state) + { + if (verbose) + printf ("CPU %d: starting from previous image file.\n", i); + } + else + { + struct cell *god; + + if (verbose) + printf ("CPU %d: no soup image found, loading god cell\n", i); + + cpu_state = state_malloc (soup_size, i); + + if ((god = load_cell (cpu_state, "god.dlo")) == 0) + { + fprintf (stderr, "dlife_soup: cannot load god cell god.dlo\n"); +#ifdef HAVE_SYSLOG + syslog (LOG_ERR, + "cannot load god cell " SPOOLDIR + "/god.dlo -- exiting"); +#endif + abort (); + } + cell_activate (cpu_state, god); + } + + cpu_state->filename = strdup (filename); + + /* Detach from the terminal. */ + close (0); + close (1); + close (2); + setsid (); + + /* Start running. */ + run_thread (cpu_state); + + exit (0); + } + } + + /* Parent process exits. The children will automatically be + * cleaned up by init(8). + */ + exit (0); +} + +/* Parse the command line arguments. */ +static void +parse_args (int argc, char *argv[]) +{ + int c; + + while ((c = getopt (argc, argv, "f:r:v")) != -1) + { + switch (c) + { + case 'f': + conf_file = optarg; + break; + case 'r': + save_dir = optarg; + break; + case 'v': + verbose = 1; + break; + default: + fprintf (stderr, + "usage: dlife_soup [-f conf-file] [-r save-dir] [-v]\n"); + exit (1); + } + } +} + +/* Return true if n is a power of 2. */ +static int +is_power_2 (int n) +{ + while ((n & 1) == 0) + n >>= 1; + return n == 1; +} + +static void +read_config_file (void) +{ + FILE *fp; + char buffer[256], *t; + + fp = fopen (conf_file, "r"); + if (fp == 0) + { + if (verbose) printf ("No configuration file found.\n"); + return; + } + + while (fgets (buffer, sizeof buffer, fp) != 0) + { + /* Remove trailing \n and \r. */ + t = buffer + strlen (buffer) - 1; + while (t >= buffer && (*t == '\n' || *t == '\r')) + *t-- = '\0'; + + /* Remove any comments (after a ``#'' character). */ + t = strchr (buffer, '#'); + if (t) + *t = '\0'; + + /* Look for lines which we understand. */ + if (sscanf (buffer, "soup_fetch_failure %u", &soup_fetch_failure) == 1) + { + /* No checks required. */ + continue; + } + if (sscanf (buffer, "inc_pc_failure %u", &inc_pc_failure) == 1) + { + /* No checks required. */ + continue; + } + if (sscanf (buffer, "insn_exec_failure %u", &insn_exec_failure) == 1) + { + /* No checks required. */ + continue; + } + if (sscanf (buffer, "access_control_failure %u", &access_control_failure) == 1) + { + /* No checks required. */ + continue; + } + if (sscanf (buffer, "cell_initialization_failure %u", &cell_initialization_failure) == 1) + { + /* No checks required. */ + continue; + } + if (sscanf (buffer, "reaper_invoke_threshold %d", &reaper_invoke_threshold) == 1) + { + if (reaper_invoke_threshold < 0 || reaper_invoke_threshold > 100) + { + fprintf (stderr, "reaper_invoke_threshold is a percentage: it must be 0 - 100\n"); + exit (1); + } + continue; + } + if (sscanf (buffer, "reaper_reap_threshold %d", &reaper_reap_threshold) == 1) + { + if (reaper_reap_threshold < 0 || reaper_reap_threshold > 100) + { + fprintf (stderr, "reaper_reap_threshold is a percentage: it must be 0 - 100\n"); + exit (1); + } + continue; + } + if (sscanf (buffer, "soup_size %d", &soup_size) == 1) + { + if (soup_size <= 0 || ! is_power_2 (soup_size)) + { + fprintf (stderr, "soup_size must be a power of 2\n"); + exit (1); + } + continue; + } + if (sscanf (buffer, "save_period %d", &save_period) == 1) + { + /* No checks required. */ + continue; + } + if (sscanf (buffer, "outgoing_period %d", &outgoing_period) == 1) + { + /* No checks required. */ + continue; + } + if (sscanf (buffer, "incoming_period %d", &incoming_period) == 1) + { + /* No checks required. */ + continue; + } + if (sscanf (buffer, "info_period %d", &info_period) == 1) + { + /* No checks required. */ + continue; + } + } +} + +/* Detect the number of CPUs available. This is very operating system + * specific. + */ + +#ifdef linux + +#ifdef __alpha__ + +static int +detect_nr_cpus () +{ + FILE *fp; + int n = -1; + char line[256]; + + fp = fopen ("/proc/cpuinfo", "r"); + if (fp == 0) + { + perror ("/proc/cpuinfo"); + fprintf (stderr, "warning: cannot detect number of CPUs available\n"); + return 1; + } + + while (fgets (line, sizeof line, fp)) + { + if (sscanf (line, "cpus detected : %d", &n) == 1) + break; + } + + fclose (fp); + + if (verbose) + printf ("number of CPUs detected: %d\n", n); + + if (n <= 0) + { + fprintf (stderr, "warning: cannot detect number of CPUs available\n"); + return 1; + } + + return n; +} + +#elif __sparc__ + +static int +detect_nr_cpus () +{ + FILE *fp; + int n = -1; + char line[256]; + + fp = fopen ("/proc/cpuinfo", "r"); + if (fp == 0) + { + perror ("/proc/cpuinfo"); + fprintf (stderr, "warning: cannot detect number of CPUs available\n"); + return 1; + } + + while (fgets (line, sizeof line, fp)) + { + if (sscanf (line, "ncpus active : %d", &n) == 1) + break; + } + + fclose (fp); + + if (verbose) + printf ("number of CPUs detected: %d\n", n); + + if (n <= 0) + { + fprintf (stderr, "warning: cannot detect number of CPUs available\n"); + return 1; + } + + return n; +} + +#else /* !__alpha__ || __sparc__ */ + +static int +detect_nr_cpus () +{ + FILE *fp; + int n, c = 0; + char line[256]; + + fp = fopen ("/proc/cpuinfo", "r"); + if (fp == 0) + { + perror ("/proc/cpuinfo"); + fprintf (stderr, "warning: cannot detect number of CPUs available\n"); + return 1; + } + + while (fgets (line, sizeof line, fp)) + { + if (sscanf (line, "processor : %d", &n) == 1 && n+1 > c) + { + c = n+1; + } + } + + fclose (fp); + + if (verbose) + printf ("number of CPUs detected: %d\n", c); + + if (c <= 0) + { + fprintf (stderr, "warning: cannot detect number of CPUs available\n"); + return 1; + } + + return c; +} + +#endif /* !__alpha__ */ + +#else /* !linux */ + +static void +detect_nr_cpus () +{ + fprintf (stderr, "warning: cannot detect number of CPUs available on this platform\n"); + return 1; +} + +#endif diff --git a/missing b/missing new file mode 120000 index 0000000..551440f --- /dev/null +++ b/missing @@ -0,0 +1 @@ +/usr/share/automake-1.4/missing \ No newline at end of file diff --git a/mkinstalldirs b/mkinstalldirs new file mode 120000 index 0000000..4b6a76d --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1 @@ +/usr/share/automake-1.4/mkinstalldirs \ No newline at end of file diff --git a/params.h b/params.h new file mode 100644 index 0000000..1c74658 --- /dev/null +++ b/params.h @@ -0,0 +1,44 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: params.h,v 1.1 2002/04/05 14:40:27 rich Exp $ + */ + +#ifndef params_h +#define params_h + +#include "config.h" + +/* Probabilities. (ie. 1 in N). */ +extern unsigned soup_fetch_failure; +extern unsigned inc_pc_failure; +extern unsigned insn_exec_failure; +extern unsigned access_control_failure; +extern unsigned cell_initialization_failure; + +/* Percentages. (0-100). */ +extern int reaper_invoke_threshold; +extern int reaper_reap_threshold; + +/* Save / load parameters. */ +extern int save_period; +extern int outgoing_period; +extern int incoming_period; +extern int info_period; +extern int max_cells_incoming_per_pass; + +#endif /* params_h */ diff --git a/random.c b/random.c new file mode 100644 index 0000000..6d11d23 --- /dev/null +++ b/random.c @@ -0,0 +1,50 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: random.c,v 1.1 2002/04/05 14:40:27 rich Exp $ + */ + +/* This module should generate high quality random numbers. It + * doesn't at the moment, but hopefully someone should be able to + * fix that. XXX + */ + +#include "config.h" + +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#include "types.h" +#include "random.h" + +void +random_init () +{ +#if PERFECT_CPU + fprintf (stderr, "warning: PERFECT_CPU is defined in \n"); +#endif + + srandom (time (NULL)); +} diff --git a/random.h b/random.h new file mode 100644 index 0000000..988b1bc --- /dev/null +++ b/random.h @@ -0,0 +1,69 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: random.h,v 1.1 2002/04/05 14:40:28 rich Exp $ + */ + +#ifndef random_h +#define random_h + +#include "config.h" + +#include + +extern void random_init (void); + +/* Define this to run on a fault-free ``perfect'' CPU. (Use this + * only when debugging). + */ +#define PERFECT_CPU 0 + +/* Return true 1 in PROBABILITY times. The argument PROBABILITY + * is not limited to just powers of 2, but it must be an integer. + */ +extern inline int +chance (unsigned probability) +{ +#if !PERFECT_CPU + return ((unsigned)random() % probability) == 0; +#else + return 0; +#endif +} + +/* Return 32 bits of randomness. */ +extern inline unsigned +get_rand_int () +{ + return (unsigned)random(); +} + +/* Return 16 bits of randomness. */ +extern inline unsigned +get_rand_short () +{ + return (unsigned)random() & 0xffff; +} + +/* Return 8 bits of randomness. */ +extern inline unsigned +get_rand_byte () +{ + return (unsigned)random() & 0xff; +} + +#endif /* random_h */ diff --git a/servers.txt b/servers.txt new file mode 100644 index 0000000..9ad063e --- /dev/null +++ b/servers.txt @@ -0,0 +1,3 @@ +# Copy of servers.txt. + +server dlife.annexia.org eu uk diff --git a/soup.c b/soup.c new file mode 100644 index 0000000..fb4a4d5 --- /dev/null +++ b/soup.c @@ -0,0 +1,440 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: soup.c,v 1.2 2002/04/05 16:47:13 rich Exp $ + */ + +#include "config.h" + +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_ASSERT_H +#include +#endif + +#include "types.h" +#include "soup.h" +#include "cell.h" +#include "random.h" +#include "state.h" +#include "crc.h" + +#define TRACE_SOUP_ALLOCATIONS 0 + +void +soup_init (struct state *state, int _soup_size) +{ + int i; + + state->soup_size = _soup_size; + state->soup_free = _soup_size; + state->soup = malloc (_soup_size); + if (state->soup == 0) { perror ("malloc"); abort (); } + + /* Fill the soup with entropy. */ + for (i = 0; i < _soup_size; ++i) + { + state->soup[i] = get_rand_byte (); + } +} + +/* Allocate a new fragment of soup. */ +struct soup_frag * +soup_frag_malloc (struct state *state, + struct soup_frag *mother_frag, reg_t len) +{ + struct soup_frag *p, *t; + int offset; + int is_first_cell = state->soup_free == state->soup_size; + +#if TRACE_SOUP_ALLOCATIONS + printf ("soup alloc: want %d bytes ", len); +#endif + + p = malloc (sizeof (struct soup_frag)); + if (p == 0) { perror ("malloc"); abort (); } + + /* Common fields. */ + p->len = len; + state->soup_free -= len; + + /* The first cell is allocated specially. */ + if (is_first_cell) + { + p->next = p; + p->prev = p; + p->base = 0; + +#if TRACE_SOUP_ALLOCATIONS + printf ("first cell 0 OK\n"); +#endif + + return p; + } + + /* If a cell has no parent, we can insert it anywhere. */ + if (mother_frag == 0) + { + /* Need to go and grab a cell at random, then search indefinitely + * for a free space. + */ + mother_frag = _cell_get_any_frag (state); + t = mother_frag; + offset = 0; + + do + { + int diff; + +#if TRACE_SOUP_ALLOCATIONS + printf ("[%d,%d:%d,%d] ", + t->base, t->base + t->len, + t->next->base, t->next->base + t->next->len); +#endif + + /* Handle the wrap-around case gracefully. */ + if (t->next->base > t->base) + diff = t->next->base - (t->base + t->len); + else + diff = t->next->base - (t->base + t->len) + state->soup_size; + + /* Is there space after this fragment? */ + if (diff >= len) + { + /* Yes: insert the cell here. */ + p->prev = t; + p->next = t->next; + p->base = (t->base + t->len) & (state->soup_size-1); + t->next->prev = p; + t->next = p; + +#if TRACE_SOUP_ALLOCATIONS + printf ("%d OK\n", p->base); +#endif + + return p; + } + + offset += diff + t->len; + t = t->next; + } + while (offset <= state->soup_size && t != mother_frag); + + /* No space for it. */ + state->soup_free += len; + free (p); + +#if TRACE_SOUP_ALLOCATIONS + printf ("FAILED\n"); +#endif + + return 0; + } + + /* Find a suitable fragment near the mother. */ + + /* Search forwards first. */ + t = mother_frag; + offset = 0; + do + { + int diff; + +#if TRACE_SOUP_ALLOCATIONS + printf ("[%d,%d:%d,%d] ", + t->base, t->base + t->len, + t->next->base, t->next->base + t->next->len); +#endif + + /* Handle the wrap-around case gracefully. */ + if (t->next->base > t->base) + diff = t->next->base - (t->base + t->len); + else + diff = t->next->base - (t->base + t->len) + state->soup_size; + + /* Is there space after this fragment? */ + if (diff >= len) + { + /* Yes: insert the cell here. */ + p->prev = t; + p->next = t->next; + p->base = (t->base + t->len) & (state->soup_size-1); + t->next->prev = p; + t->next = p; + +#if TRACE_SOUP_ALLOCATIONS + printf ("%d OK\n", p->base); +#endif + + return p; + } + + offset += diff + t->len; + t = t->next; + } + while (offset <= MAX_SPAWN_DISTANCE && t != mother_frag); + + /* Search backwards. */ + t = mother_frag; + offset = 0; + do + { + int diff; + +#if TRACE_SOUP_ALLOCATIONS + printf ("[%d,%d:%d,%d] ", + t->prev->base, t->prev->base + t->prev->len, + t->base, t->base + t->len); +#endif + + /* Handle the wrap-around case gracefully. */ + if (t->prev->base < t->base) + diff = t->base - (t->prev->base + t->prev->len); + else + diff = t->base - (t->prev->base + t->prev->len) + state->soup_size; + + /* Is there space before this fragment? */ + if (diff >= len) + { + /* Yes: insert the cell here. */ + p->prev = t->prev; + p->next = t; + p->base = (t->base - len) & (state->soup_size-1); + p->len = len; + t->prev->next = p; + t->prev = p; + +#if TRACE_SOUP_ALLOCATIONS + printf ("%d OK\n", p->base); +#endif + + return p; + } + + offset += diff + t->prev->len; + t = t->prev; + } + while (offset <= MAX_SPAWN_DISTANCE && t != mother_frag); + + /* No space for it. */ + state->soup_free += len; + free (p); + +#if TRACE_SOUP_ALLOCATIONS + printf ("FAILED\n"); +#endif + + return 0; +} + +/* Free up a soup fragment. */ +void +soup_frag_free (struct state *state, + struct soup_frag *frag) +{ + /* NB. We ignore the case of freeing up the single last remaining + * fragment, since that should never happen in real life. + */ + frag->next->prev = frag->prev; + frag->prev->next = frag->next; + + state->soup_free += frag->len; + + free (frag); +} + +/* Compute the CRC for a frag. */ +crc_t +soup_frag_compute_crc32 (const struct state *state, + const struct soup_frag *frag) +{ + /* Take care of the case where a cell straddles the end of the soup. */ + if (frag->base + frag->len <= state->soup_size) + { + return compute_crc32 (state->soup + frag->base, frag->len); + } + else + { + crc_t crc = compute_crc32 (state->soup + frag->base, + state->soup_size - frag->base); + return incr_compute_crc32 (crc, state->soup, + frag->len - (state->soup_size - frag->base)); + } + +} + +/* This function checks that the soup is consistent. We are passed + * one fragment (at random) and walk the circular linked list, + * examining the fragments to ensure they are in order and do not + * overlap. + */ +void +soup_check (struct state *state) +{ + const struct soup_frag *start_frag = _cell_get_any_frag (state); + const struct soup_frag *frag = start_frag; + int nr_frags = 0; + int soup_free = state->soup_size; + + do + { + assert (0 <= frag->base && frag->base < state->soup_size); + assert (frag->len > 0); + + assert (frag->next->prev == frag); + assert (frag->prev->next == frag); + + if (frag->prev->base < frag->base) + assert (frag->prev->base + frag->prev->len <= frag->base); + else + assert (frag->prev->base + frag->prev->len <= frag->base + state->soup_size); + + if (frag->base < frag->next->base) + assert (frag->base + frag->len <= frag->next->base); + else + assert (frag->base + frag->len <= frag->next->base + state->soup_size); + + soup_free -= frag->len; + + frag = frag->next; + nr_frags++; + } + while (frag != start_frag); + + assert (nr_frags == state->nr_cells_allocated); + assert (soup_free == state->soup_free); +} + +/* Dump the soup and soup structures out to a file. This function is + * non-destructive. + */ +void +soup_state_save (struct state *state, FILE *fp) +{ + struct soup_frag *start_frag, *frag; + + /* Write out the size of the soup. */ + fwrite (&state->soup_size, sizeof state->soup_size, 1, fp); + fwrite (&state->soup_free, sizeof state->soup_free, 1, fp); + + /* Write out the soup itself. */ + fwrite (state->soup, 1, state->soup_size, fp); + + /* Write out the number of fragments. Note that this is the same + * as the number of allocated cells. + */ + fwrite (&state->nr_cells_allocated, + sizeof state->nr_cells_allocated, 1, fp); + + /* Write out the fragment list. */ + frag = start_frag = _cell_get_any_frag (state); + do + { + fwrite (frag, sizeof (struct soup_frag), 1, fp); + + frag = frag->next; + } + while (frag != start_frag); +} + +/* Load the soup state from a previously saved file. */ +void +soup_state_load (struct state *state, FILE *fp) +{ + int _soup_size, nr_frags, i; + struct soup_frag *first_frag = 0, *prev_frag = 0; + + /* Load the size of the soup expected. */ + if (fread (&_soup_size, sizeof _soup_size, 1, fp) != 1) + { + fprintf (stderr, "error in soup state\n"); + abort (); + } + if (state->soup_size != _soup_size) + { + fprintf (stderr, "soup size doesn't match - can't load this soup image\n"); + abort (); + } + if (fread (&state->soup_free, sizeof state->soup_free, 1, fp) != 1) + { + fprintf (stderr, "error in soup state\n"); + abort (); + } + if (state->soup_free > state->soup_size) + { + fprintf (stderr, "soup free > soup_size - can't load this soup image\n"); + abort (); + } + + /* Load the soup itself. */ + if (fread (state->soup, 1, _soup_size, fp) != _soup_size) + { + fprintf (stderr, "error in soup state\n"); + abort (); + } + + /* Load the number of fragments expected. */ + if (fread (&nr_frags, sizeof nr_frags, 1, fp) != 1) + { + fprintf (stderr, "error in soup state\n"); + abort (); + } + if (nr_frags != state->nr_cells_allocated) + { + fprintf (stderr, "nr_frags != nr_cells_allocated - can't load this soup image\n"); + abort (); + } + + /* Load each fragment. */ + for (i = 0; i < nr_frags; ++i) + { + struct soup_frag *p; + + p = malloc (sizeof (struct soup_frag)); + if (p == 0) { perror ("malloc"); abort (); } + + if (fread (p, sizeof (struct soup_frag), 1, fp) != 1) + { + fprintf (stderr, "error in soup state\n"); + abort (); + } + + if (i == 0) + first_frag = p; + + /* Find the cell which references this fragment and fix it up. */ + _cell_fixup_soup_ref (state, p->base, p); + + /* Join the fragments to form a circular linked list. */ + if (prev_frag) + { + p->prev = prev_frag; + p->prev->next = p; + } + + prev_frag = p; + } + + /* Finish off the circular linked list. */ + first_frag->prev = prev_frag; + prev_frag->next = first_frag; +} diff --git a/soup.conf b/soup.conf new file mode 100644 index 0000000..338cc72 --- /dev/null +++ b/soup.conf @@ -0,0 +1,65 @@ +# DLIFE soup configuration file. + +#---------------------------------------------------------------------- +# The size of the soup (in bytes). +# +# This parameter must be a power of 2. If you change this parameter, +# then you will have to reinitialize the soup image. You cannot load +# a soup image from one version of the program into another version +# with a different soup size. + +soup_size 131072 + +#---------------------------------------------------------------------- +# Failure probabilities. +# +# All probabilities are expressed in the form ``1 in N'' where N is +# an integer between 1 and about 4 billion. Larger values of N means +# the event is rarer. You can dramatically change the behaviour of +# the environment by changing these parameters - from a highly- +# irradiated soup similar to the early earth (and NOT supporting +# life) - to an almost completely stable soup free from almost any +# mutation. + +# The probability that fetching a value from the soup will fail. + +soup_fetch_failure 1000000 + +# The probability that the program counter will fail to increment +# after an instruction has been executed. + +inc_pc_failure 1000000 + +# The overall probability that an instruction will fail to execute +# correctly. + +insn_exec_failure 1000000 + +# The probability that the access control mechanisms (which govern +# what addresses a cell may write to) will fail. It is OK to have +# this probability quite large (ie. small N) so that cells may try +# to ``invade'' other cells. + +access_control_failure 10 + +# The probability that a newly created cell isn't initialized correctly - +# ie. that the registers and stack don't start off at zero. + +cell_initialization_failure 1000000 + +#---------------------------------------------------------------------- +# Grim reaper configuration. +# +# These parameters control when and for how long the grim reaper +# comes to life and kills off sick cells. These two parameters are +# expressed as percentages of soup used (ie. ``80'' means the soup +# is 80% full). + +# The grim reaper is invoked when the soup is this full. + +reaper_invoke_threshold 80 + +# The grim reaper runs until the soup is this full (and then +# goes back to sleep again). + +reaper_reap_threshold 79 diff --git a/soup.h b/soup.h new file mode 100644 index 0000000..e9cceed --- /dev/null +++ b/soup.h @@ -0,0 +1,79 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: soup.h,v 1.1 2002/04/05 14:40:28 rich Exp $ + */ + +#ifndef soup_h +#define soup_h + +#include "config.h" + +#include "types.h" +#include "state.h" +#include "crc.h" + +/* How far away can a daughter be from its mother? */ +#define MAX_SPAWN_DISTANCE 8192 + +struct soup_frag +{ + addr_t base; /* Base address of this fragment. */ + int len; /* Length of this fragment. */ + + /* These are kept on a circular doubly-linked list. */ + struct soup_frag *next, *prev; +}; + +extern inline addr_t +raddr_to_addr (const struct state *state, + const struct soup_frag *frag, reg_t raddr) +{ + return (frag->base + raddr) & (state->soup_size - 1); +} + +extern inline int +get_soup (const struct state *state, + const struct soup_frag *frag, reg_t raddr) +{ + addr_t addr = raddr_to_addr (state, frag, raddr); + return state->soup[addr]; +} + +extern inline void +set_soup (struct state *state, + const struct soup_frag *frag, int v, reg_t raddr) +{ + addr_t addr = raddr_to_addr (state, frag, raddr); + state->soup[addr] = v; +} + +extern void soup_init (struct state *state, int _soup_size); + +extern struct soup_frag *soup_frag_malloc (struct state *state, + struct soup_frag *, reg_t); +extern void soup_frag_free (struct state *state, struct soup_frag *); + +extern void soup_state_save (struct state *state, FILE *fp); +extern void soup_state_load (struct state *state, FILE *fp); + +extern void soup_check (struct state *state); + +extern crc_t soup_frag_compute_crc32 (const struct state *state, + const struct soup_frag *frag); + +#endif /* soup_h */ diff --git a/stamp-h.in b/stamp-h.in new file mode 100644 index 0000000..e69de29 diff --git a/state.c b/state.c new file mode 100644 index 0000000..fa7a8f1 --- /dev/null +++ b/state.c @@ -0,0 +1,67 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: state.c,v 1.2 2002/04/05 16:47:13 rich Exp $ + */ + +#include "config.h" + +#include +#include + +#include "state.h" +#include "soup.h" +#include "cell.h" + +struct state * +state_malloc (int _soup_size, int thread_num) +{ + struct state *p = malloc (sizeof (struct state)); + if (p == 0) { perror ("malloc"); abort (); } + + p->cell_cycle = 0; + p->nr_cells_alive = 0; + p->nr_cells_allocated = 0; + dlink_list_init (&p->alive_list, offsetof (struct cell, next)); + dlink_list_init (&p->best_list, offsetof (struct cell, worse)); + soup_init (p, _soup_size); + p->filename = 0; + p->thread_num = thread_num; + + return p; +} + +void +state_free (struct state *state) +{ + struct cell *p; + + /* Free up cells. This also cleans up soup frags. */ + for (p = (struct cell *) state->alive_list.first; p; p = p->next) + { + cell_kill (state, p); + } + + /* Free up soup. */ + free (state->soup); + + /* Free up soup image filename. */ + if (state->filename) free (state->filename); + + /* Free up structure. */ + free (state); +} diff --git a/state.h b/state.h new file mode 100644 index 0000000..ce242b4 --- /dev/null +++ b/state.h @@ -0,0 +1,66 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: state.h,v 1.1 2002/04/05 14:40:28 rich Exp $ + */ + +#ifndef state_h +#define state_h + +#include "dlink.h" +#include "types.h" + +struct state +{ + /* The number of cycles we have been running for. */ + unsigned long long cell_cycle; + + /* The number of cells alive (running and on the alive list). */ + int nr_cells_alive; + + /* The number of cells allocated (alive + undivided daughters). */ + int nr_cells_allocated; + + /* The list of cells currently alive (running). Some cells may also + * exist in an undivided state. + */ + dlink_list_t alive_list; + + /* The same list of cells, kept in order of best (fewest errors) to + * worse (most errors). This allows the grim reaper to quickly remove + * dying cells. + */ + dlink_list_t best_list; + + /* The soup. */ + byte_t *soup; + + /* Number of bytes in soup, and number of bytes free in soup. */ + int soup_size; + int soup_free; + + /* Filename of the soup image (for this thread). */ + char *filename; + + /* Thread number (first thread is number 0). */ + int thread_num; +}; + +extern struct state *state_malloc (int _soup_size, int thread_num); +extern void state_free (struct state *); + +#endif /* state_h */ diff --git a/types.h b/types.h new file mode 100644 index 0000000..504c633 --- /dev/null +++ b/types.h @@ -0,0 +1,43 @@ +/* DLIFE Copyright (C) 2000 Richard W.M. Jones + * and other authors listed in the ``AUTHORS'' file. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: types.h,v 1.1 2002/04/05 14:40:28 rich Exp $ + */ + +#ifndef types_h +#define types_h + +#include "config.h" + +/* Apparently these are now defined by the ISO C 9x standard. */ +#ifdef HAVE_STDINT_H +#include +#else +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +#endif + +typedef uint8_t byte_t; +typedef int32_t addr_t; +typedef int16_t reg_t; + +#endif /* types_h */