This commit was manufactured by cvs2svn to create branch 'pth-branch'. pth-branch
authorMatthew Mondor <mmondor@pulsar-zone.net>
Wed, 13 Dec 2006 14:37:13 +0000 (14:37 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Wed, 13 Dec 2006 14:37:13 +0000 (14:37 +0000)
428 files changed:
Xisop/LICENSE [deleted file]
Xisop/README [deleted file]
Xisop/TODO [deleted file]
Xisop/doc/clean.sh [deleted file]
Xisop/doc/make.sh [deleted file]
Xisop/doc/xisop.lyx [deleted file]
Xisop/src/clean.sh [deleted file]
Xisop/src/common/clean.sh [deleted file]
Xisop/src/common/kernel/clean.sh [deleted file]
Xisop/src/common/kernel/debug.c [deleted file]
Xisop/src/common/kernel/debug.h [deleted file]
Xisop/src/common/kernel/device.c [deleted file]
Xisop/src/common/kernel/device.h [deleted file]
Xisop/src/common/kernel/exception.c [deleted file]
Xisop/src/common/kernel/exception.h [deleted file]
Xisop/src/common/kernel/main.c [deleted file]
Xisop/src/common/kernel/main.h [deleted file]
Xisop/src/common/kernel/make.sh [deleted file]
Xisop/src/common/kernel/memory.c [deleted file]
Xisop/src/common/kernel/memory.h [deleted file]
Xisop/src/common/kernel/object.h [deleted file]
Xisop/src/common/kernel/port.c [deleted file]
Xisop/src/common/kernel/port.h [deleted file]
Xisop/src/common/kernel/scheduler.c [deleted file]
Xisop/src/common/kernel/scheduler.h [deleted file]
Xisop/src/common/kernel/signal.c [deleted file]
Xisop/src/common/kernel/signal.h [deleted file]
Xisop/src/common/kernel/statistic.c [deleted file]
Xisop/src/common/kernel/statistic.h [deleted file]
Xisop/src/common/kernel/syscall.c [deleted file]
Xisop/src/common/kernel/syscall.h [deleted file]
Xisop/src/common/kernel/task.c [deleted file]
Xisop/src/common/kernel/task.h [deleted file]
Xisop/src/common/kernlib/clean.sh [deleted file]
Xisop/src/common/kernlib/fifo.h [deleted file]
Xisop/src/common/kernlib/hash.c [deleted file]
Xisop/src/common/kernlib/hash.h [deleted file]
Xisop/src/common/kernlib/lifo.h [deleted file]
Xisop/src/common/kernlib/list.h [deleted file]
Xisop/src/common/kernlib/make.sh [deleted file]
Xisop/src/common/kernlib/rand.c [deleted file]
Xisop/src/common/kernlib/rand.h [deleted file]
Xisop/src/common/kernlib/setjmp.h [deleted file]
Xisop/src/common/kernlib/string.h [deleted file]
Xisop/src/common/kernlib/string/_strcat.c [deleted file]
Xisop/src/common/kernlib/string/_strcpy.c [deleted file]
Xisop/src/common/kernlib/string/_strdup.c [deleted file]
Xisop/src/common/kernlib/string/_strncat.c [deleted file]
Xisop/src/common/kernlib/string/_strncpy.c [deleted file]
Xisop/src/common/kernlib/string/_strndup.c [deleted file]
Xisop/src/common/kernlib/string/_strrev.c [deleted file]
Xisop/src/common/kernlib/string/bstr_alloc.c [deleted file]
Xisop/src/common/kernlib/string/bstr_free.c [deleted file]
Xisop/src/common/kernlib/string/bstr_new.c [deleted file]
Xisop/src/common/kernlib/string/case.c [deleted file]
Xisop/src/common/kernlib/string/htol.c [deleted file]
Xisop/src/common/kernlib/string/memcmp.c [deleted file]
Xisop/src/common/kernlib/string/memcpy.c [deleted file]
Xisop/src/common/kernlib/string/memhash32.c [deleted file]
Xisop/src/common/kernlib/string/memmove.c [deleted file]
Xisop/src/common/kernlib/string/memset.c [deleted file]
Xisop/src/common/kernlib/string/pageclr.c [deleted file]
Xisop/src/common/kernlib/string/straspl.c [deleted file]
Xisop/src/common/kernlib/string/strchr.c [deleted file]
Xisop/src/common/kernlib/string/strcmp.c [deleted file]
Xisop/src/common/kernlib/string/strlen.c [deleted file]
Xisop/src/common/kernlib/string/strnchr.c [deleted file]
Xisop/src/common/kernlib/string/strncmp.c [deleted file]
Xisop/src/common/kernlib/string/strnlen.c [deleted file]
Xisop/src/common/kernlib/string/strnrchr.c [deleted file]
Xisop/src/common/kernlib/string/strrchr.c [deleted file]
Xisop/src/common/kernlib/string/strspl.c [deleted file]
Xisop/src/common/make.sh [deleted file]
Xisop/src/common/types.h [deleted file]
Xisop/src/config.h [deleted file]
Xisop/src/generic_makedefs.sh [deleted file]
Xisop/src/make.sh [deleted file]
Xisop/src/ports/amiga/boot/DOTuaerc [deleted file]
Xisop/src/ports/amiga/boot/README [deleted file]
Xisop/src/ports/amiga/boot/bootf/bootf_c.c [deleted file]
Xisop/src/ports/amiga/boot/bootf/bootf_s.s [deleted file]
Xisop/src/ports/amiga/boot/bootf/bootf_script.ld [deleted file]
Xisop/src/ports/amiga/boot/clean.sh [deleted file]
Xisop/src/ports/amiga/boot/config.h [deleted file]
Xisop/src/ports/amiga/boot/image_script.ld [deleted file]
Xisop/src/ports/amiga/boot/init.c [deleted file]
Xisop/src/ports/amiga/boot/make.sh [deleted file]
Xisop/src/ports/amiga/boot/tools/aosbblock.c [deleted file]
Xisop/src/ports/amiga/boot/tools/config.c [deleted file]
Xisop/src/ports/amiga/boot/tools/dumpkern.c [deleted file]
Xisop/src/ports/amiga/clean.sh [deleted file]
Xisop/src/ports/amiga/make.sh [deleted file]
Xisop/src/ports/amiga/makedefs.sh [deleted file]
Xisop/src/ports/amiga/support.h [deleted file]
Xisop/src/ports/amiga/support_c.c [deleted file]
Xisop/src/ports/amiga/support_s.s [deleted file]
Xisop/src/processors/i386/make.sh [deleted file]
Xisop/src/processors/i386/support.h [deleted file]
Xisop/src/processors/i386/support.s [deleted file]
Xisop/src/processors/m68k/clean.sh [deleted file]
Xisop/src/processors/m68k/make.sh [deleted file]
Xisop/src/processors/m68k/math/README [deleted file]
Xisop/src/processors/m68k/math/divsi3.s [deleted file]
Xisop/src/processors/m68k/math/modsi3.s [deleted file]
Xisop/src/processors/m68k/math/mulsi3.s [deleted file]
Xisop/src/processors/m68k/math/udivsi3.s [deleted file]
Xisop/src/processors/m68k/math/umodsi3.s [deleted file]
Xisop/src/processors/m68k/support.h [deleted file]
Xisop/src/processors/m68k/support.s [deleted file]
mmsoftware/BUGS [deleted file]
mmsoftware/LICENSE [deleted file]
mmsoftware/TODO [deleted file]
mmsoftware/apache-mmstat/GNUmakefile [deleted file]
mmsoftware/apache-mmstat/apache-mmstat.8 [deleted file]
mmsoftware/apache-mmstat/apache-mmstat.c [deleted file]
mmsoftware/apache-mmstat/makepart.sh [deleted file]
mmsoftware/bot/Makefile [deleted file]
mmsoftware/bot/irc.txt [deleted file]
mmsoftware/bot/newbot.c [deleted file]
mmsoftware/bot/zenbot.c [deleted file]
mmsoftware/clean.sh [deleted file]
mmsoftware/install.sh [deleted file]
mmsoftware/js/classes/TODO.txt [deleted file]
mmsoftware/js/classes/js_cgi.c [deleted file]
mmsoftware/js/classes/js_cgi.h [deleted file]
mmsoftware/js/classes/js_dir.c [deleted file]
mmsoftware/js/classes/js_dir.h [deleted file]
mmsoftware/js/classes/js_errno.c [deleted file]
mmsoftware/js/classes/js_errno.h [deleted file]
mmsoftware/js/classes/js_fd.c [deleted file]
mmsoftware/js/classes/js_fd.h [deleted file]
mmsoftware/js/classes/js_file.c [deleted file]
mmsoftware/js/classes/js_file.h [deleted file]
mmsoftware/js/classes/js_fs.c [deleted file]
mmsoftware/js/classes/js_fs.h [deleted file]
mmsoftware/js/classes/js_gcroot.c [deleted file]
mmsoftware/js/classes/js_gcroot.h [deleted file]
mmsoftware/js/classes/js_gd.c [deleted file]
mmsoftware/js/classes/js_gd.h [deleted file]
mmsoftware/js/classes/js_global.c [deleted file]
mmsoftware/js/classes/js_global.h [deleted file]
mmsoftware/js/classes/js_mysql.c [deleted file]
mmsoftware/js/classes/js_mysql.h [deleted file]
mmsoftware/js/classes/js_pgsql.c [deleted file]
mmsoftware/js/classes/js_pgsql.h [deleted file]
mmsoftware/js/classes/js_signal.c [deleted file]
mmsoftware/js/classes/js_signal.h [deleted file]
mmsoftware/js/classes/js_syslog.c [deleted file]
mmsoftware/js/classes/js_syslog.h [deleted file]
mmsoftware/js/js-appserv/app/test/handle.js [deleted file]
mmsoftware/js/js-appserv/app/test/main.js [deleted file]
mmsoftware/js/js-appserv/app/test/session.js [deleted file]
mmsoftware/js/js-appserv/app/test/test.conf [deleted file]
mmsoftware/js/js-appserv/doc/js-appserv-protocol.lyx [deleted file]
mmsoftware/js/js-appserv/src/GNUmakefile [deleted file]
mmsoftware/js/js-appserv/src/js-appserv.8 [deleted file]
mmsoftware/js/js-appserv/src/js-appserv.c [deleted file]
mmsoftware/js/js-appserv/src/js-appserv.conf.5 [deleted file]
mmsoftware/js/js-sh/app/httpd/httpd.js [deleted file]
mmsoftware/js/js-sh/app/httpd/options.js [deleted file]
mmsoftware/js/js-sh/app/irclog/config.js [deleted file]
mmsoftware/js/js-sh/app/irclog/irclog.js [deleted file]
mmsoftware/js/js-sh/app/randstat/randstat.js [deleted file]
mmsoftware/js/js-sh/app/thumb/thumb.js [deleted file]
mmsoftware/js/js-sh/src/GNUmakefile [deleted file]
mmsoftware/js/js-sh/src/js-sh.c [deleted file]
mmsoftware/js/jslib/fd.js [deleted file]
mmsoftware/js/jslib/json.js [deleted file]
mmsoftware/js/jslib/ml_clean.js [deleted file]
mmsoftware/js/jslib/ml_machine.js [deleted file]
mmsoftware/js/jslib/pgsql.js [deleted file]
mmsoftware/js/jslib/root.js [deleted file]
mmsoftware/js/jslib/string.js [deleted file]
mmsoftware/js/util/spidermonkey-config [deleted file]
mmsoftware/make.sh [deleted file]
mmsoftware/mmanoncvs/GNUmakefile [deleted file]
mmsoftware/mmanoncvs/mmanoncvs.8 [deleted file]
mmsoftware/mmanoncvs/mmanoncvs.c [deleted file]
mmsoftware/mmanoncvs/mmanoncvs.conf.5 [deleted file]
mmsoftware/mmanoncvs/mmanoncvs.list.5 [deleted file]
mmsoftware/mmidentd/GNUmakefile [deleted file]
mmsoftware/mmidentd/mmidentd.c [deleted file]
mmsoftware/mmmail2/ChangeLog [deleted file]
mmsoftware/mmmail2/README [deleted file]
mmsoftware/mmmail2/notes/convert.sh [deleted file]
mmsoftware/mmmail2/notes/mmmail-design.lyx [deleted file]
mmsoftware/mmmail2/notes/mmmail-tables.dia [deleted file]
mmsoftware/mmpasswd/GNUmakefile [deleted file]
mmsoftware/mmpasswd/Makefile [deleted file]
mmsoftware/mmpasswd/make.sh [deleted file]
mmsoftware/mmpasswd/makepart.sh [deleted file]
mmsoftware/mmpasswd/mmpasswd.8 [deleted file]
mmsoftware/mmpasswd/mmpasswd.c [deleted file]
mmsoftware/mmsendmail/GNUmakefile [deleted file]
mmsoftware/mmsendmail/Makefile [deleted file]
mmsoftware/mmsendmail/mmsendmail.c [deleted file]
mmsoftware/mmspawnd/GNUmakefile [deleted file]
mmsoftware/mmspawnd/mmspawnd.8 [deleted file]
mmsoftware/mmspawnd/mmspawnd.c [deleted file]
mmsoftware/mmspawnd/mmspawnd.conf.5 [deleted file]
mmsoftware/mmspawnd/new/GNUmakefile [deleted file]
mmsoftware/mmspawnd/new/README [deleted file]
mmsoftware/mmspawnd/new/mmspawnd.c [deleted file]
mmsoftware/mmspawnd2/GNUmakefile [deleted file]
mmsoftware/mmspawnd2/mmspawnd.8 [deleted file]
mmsoftware/mmspawnd2/mmspawnd.c [deleted file]
mmsoftware/mmspawnd2/mmspawnd.conf.5 [deleted file]
mmsoftware/mmstatd/ChangeLog [deleted file]
mmsoftware/mmstatd/GNUmakefile [deleted file]
mmsoftware/mmstatd/README [deleted file]
mmsoftware/mmstatd/clean.sh [deleted file]
mmsoftware/mmstatd/etc/mmstatd.conf [deleted file]
mmsoftware/mmstatd/future.txt [deleted file]
mmsoftware/mmstatd/install.sh [deleted file]
mmsoftware/mmstatd/make.sh [deleted file]
mmsoftware/mmstatd/src/Makefile [deleted file]
mmsoftware/mmstatd/src/makepart.sh [deleted file]
mmsoftware/mmstatd/src/mmstat.8 [deleted file]
mmsoftware/mmstatd/src/mmstat.c [deleted file]
mmsoftware/mmstatd/src/mmstatd.8 [deleted file]
mmsoftware/mmstatd/src/mmstatd.c [deleted file]
mmsoftware/mmstatd/src/mmstatd.conf.5 [deleted file]
mmsoftware/mmstatd/src/mmstatd.h [deleted file]
mmsoftware/mmsucom/GNUmakefile [deleted file]
mmsoftware/mmsucom/Makefile [deleted file]
mmsoftware/mmsucom/README [deleted file]
mmsoftware/mmsucom/mmsucom.c [deleted file]
mmsoftware/mmsucom/mmsucomd.c [deleted file]
mmsoftware/mmsucom/mmsucomd.conf [deleted file]
mmsoftware/stringtest/GNUmakefile [deleted file]
mmsoftware/stringtest/stringtest.c [deleted file]
site/contributors.html [deleted file]
site/cvs.html [deleted file]
site/donations.html [deleted file]
site/favicon.ico [deleted file]
site/images/CVS.jpg [deleted file]
site/images/key.jpg [deleted file]
site/images/sigil.jpg [deleted file]
site/index.html [deleted file]
site/mirrors.html [deleted file]
site/new/TODO [deleted file]
site/new/build/GNUmakefile [deleted file]
site/new/build/README [deleted file]
site/new/build/TODO [deleted file]
site/new/build/english/faq_mmftpd.txt [deleted file]
site/new/build/english/faq_mmmail.txt [deleted file]
site/new/build/english/faq_mmstatd.txt [deleted file]
site/new/build/english/menu_languages.txt [deleted file]
site/new/build/english/menu_main.txt [deleted file]
site/new/build/english/menu_mirrors.txt [deleted file]
site/new/build/english/page_contact.txt [deleted file]
site/new/build/english/page_contributors.txt [deleted file]
site/new/build/english/page_cvs.txt [deleted file]
site/new/build/english/page_donations.txt [deleted file]
site/new/build/english/page_index.txt [deleted file]
site/new/build/english/page_mirrors.txt [deleted file]
site/new/build/english/page_philosophy.txt [deleted file]
site/new/build/english/page_projects.txt [deleted file]
site/new/build/english/page_software.txt [deleted file]
site/new/build/english/soft_descriptions.txt [deleted file]
site/new/build/mmsite.c [deleted file]
site/new/build/mmsite.conf [deleted file]
site/new/build/site_faq.txt [deleted file]
site/new/build/site_languages.txt [deleted file]
site/new/build/site_mirrors.txt [deleted file]
site/new/build/site_pages.txt [deleted file]
site/new/build/site_software.txt [deleted file]
site/new/build/soft_development.txt [deleted file]
site/new/build/soft_old.txt [deleted file]
site/new/build/soft_stable.txt [deleted file]
site/philosophy.html [deleted file]
site/projects.html [deleted file]
site/software.html [deleted file]
tests/entropy/README [deleted file]
tests/entropy/entropy_disk.c [deleted file]
tests/js-test/README [deleted file]
tests/js-test/js/copy.js [deleted file]
tests/js-test/js/fd.js [deleted file]
tests/js-test/js/game/objects.js [deleted file]
tests/js-test/js/httpd/httpd.js [deleted file]
tests/js-test/js/httpd/ml_clean.js [deleted file]
tests/js-test/js/httpd/ml_machine.js [deleted file]
tests/js-test/js/httpd/options.js [deleted file]
tests/js-test/js/httpd/root.js [deleted file]
tests/js-test/js/httpd/string.js [deleted file]
tests/js-test/js/ml.js [deleted file]
tests/js-test/js/ml2.js [deleted file]
tests/js-test/js/ml3.js [deleted file]
tests/js-test/js/ml4.js [deleted file]
tests/js-test/js/ml5.js [deleted file]
tests/js-test/js/ml6.js [deleted file]
tests/js-test/js/parse.js [deleted file]
tests/js-test/js/poll_test.js [deleted file]
tests/js-test/js/sock_httpd.js [deleted file]
tests/js-test/js/sock_listen.js [deleted file]
tests/js-test/js/test.js [deleted file]
tests/js-test/js/test2.js [deleted file]
tests/js-test/js/test3.js [deleted file]
tests/js-test/src/GNUmakefile [deleted file]
tests/js-test/src/classes/js_errno.c [deleted file]
tests/js-test/src/classes/js_errno.h [deleted file]
tests/js-test/src/classes/js_fd.c [deleted file]
tests/js-test/src/classes/js_fd.h [deleted file]
tests/js-test/src/classes/js_global.c [deleted file]
tests/js-test/src/classes/js_global.h [deleted file]
tests/js-test/src/classes/js_mysql.c [deleted file]
tests/js-test/src/classes/js_mysql.h [deleted file]
tests/js-test/src/classes/js_pgsql.c [deleted file]
tests/js-test/src/classes/js_pgsql.h [deleted file]
tests/js-test/src/classes/js_signal.c [deleted file]
tests/js-test/src/classes/js_signal.h [deleted file]
tests/js-test/src/js-server.c [deleted file]
tests/js-test/util/spidermonkey-config [deleted file]
tests/kqueue/GNUmakefile [deleted file]
tests/kqueue/README [deleted file]
tests/kqueue/client.c [deleted file]
tests/kqueue/client.h [deleted file]
tests/kqueue/conf.h [deleted file]
tests/kqueue/daemon.c [deleted file]
tests/kqueue/daemon.h [deleted file]
tests/kqueue/kqueue.c [deleted file]
tests/kqueue/kqueue.h [deleted file]
tests/kqueue/main.c [deleted file]
tests/kqueue/net.c [deleted file]
tests/kqueue/net.h [deleted file]
tests/kqueue/packets.c [deleted file]
tests/kqueue/packets.h [deleted file]
tests/kqueue/recvq.c [deleted file]
tests/kqueue/recvq.h [deleted file]
tests/kqueue/sendq.c [deleted file]
tests/kqueue/sendq.h [deleted file]
tests/memory/README [deleted file]
tests/pthread_utils/GNUmakefile [deleted file]
tests/pthread_utils/README [deleted file]
tests/pthread_utils/mm_pthread_debug.h [deleted file]
tests/pthread_utils/mm_pthread_msg.c [deleted file]
tests/pthread_utils/mm_pthread_msg.h [deleted file]
tests/pthread_utils/mm_pthread_poll.c [deleted file]
tests/pthread_utils/mm_pthread_poll.h [deleted file]
tests/pthread_utils/mm_pthread_pool.c [deleted file]
tests/pthread_utils/mm_pthread_pool.h [deleted file]
tests/pthread_utils/mm_pthread_sleep.c [deleted file]
tests/pthread_utils/mm_pthread_sleep.h [deleted file]
tests/pthread_utils/tests/msg_test.c [deleted file]
tests/pthread_utils/tests/poll_test.c [deleted file]
tests/pthread_utils/tests/polltest.c [deleted file]
tests/pthread_utils/tests/sigtest.c [deleted file]
tests/rotate/GNUmakefile [deleted file]
tests/rotate/main.c [deleted file]
tests/sdl-client/GNUmakefile [deleted file]
tests/sdl-client/README [deleted file]
tests/sdl-client/bmp/FedCA.bmp [deleted file]
tests/sdl-client/bmp/README [deleted file]
tests/sdl-client/bmp/RomDD.bmp [deleted file]
tests/sdl-client/bmp/fedship.bmp [deleted file]
tests/sdl-client/bmp/indship.bmp [deleted file]
tests/sdl-client/bmp/kliship.bmp [deleted file]
tests/sdl-client/bmp/misc-fixed-bold-r-normal--13-120-75-75-c-80-iso8859-1.bmp [deleted file]
tests/sdl-client/bmp/misc-fixed-bold-r-normal--15-120-100-100-c-90-iso8859-1.bmp [deleted file]
tests/sdl-client/bmp/misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-1.bmp [deleted file]
tests/sdl-client/bmp/misc-fixed-medium-r-normal--15-120-100-100-c-90-iso8859-1.bmp [deleted file]
tests/sdl-client/bmp/oriship.bmp [deleted file]
tests/sdl-client/bmp/romship.bmp [deleted file]
tests/sdl-client/bmp/sbexpl.bmp [deleted file]
tests/sdl-client/bmp/shexpl.bmp [deleted file]
tests/sdl-client/conf.h [deleted file]
tests/sdl-client/debug.c [deleted file]
tests/sdl-client/debug.h [deleted file]
tests/sdl-client/decode.c [deleted file]
tests/sdl-client/decode.h [deleted file]
tests/sdl-client/dlist.h [deleted file]
tests/sdl-client/encode.c [deleted file]
tests/sdl-client/fnt/10x20.fnt [deleted file]
tests/sdl-client/fnt/5x7.fnt [deleted file]
tests/sdl-client/fnt/5x8.fnt [deleted file]
tests/sdl-client/fnt/6x10.fnt [deleted file]
tests/sdl-client/fnt/6x12.fnt [deleted file]
tests/sdl-client/fnt/6x13.fnt [deleted file]
tests/sdl-client/fnt/6x13B.fnt [deleted file]
tests/sdl-client/fnt/6x13O.fnt [deleted file]
tests/sdl-client/fnt/6x9.fnt [deleted file]
tests/sdl-client/fnt/7x13.fnt [deleted file]
tests/sdl-client/fnt/7x13B.fnt [deleted file]
tests/sdl-client/fnt/7x13O.fnt [deleted file]
tests/sdl-client/fnt/7x14.fnt [deleted file]
tests/sdl-client/fnt/7x14B.fnt [deleted file]
tests/sdl-client/fnt/8x13.fnt [deleted file]
tests/sdl-client/fnt/8x13B.fnt [deleted file]
tests/sdl-client/fnt/8x13O.fnt [deleted file]
tests/sdl-client/fnt/9x15.fnt [deleted file]
tests/sdl-client/fnt/9x15B.fnt [deleted file]
tests/sdl-client/fnt/9x18.fnt [deleted file]
tests/sdl-client/fnt/9x18B.fnt [deleted file]
tests/sdl-client/main.c [deleted file]
tests/sdl-client/main.h [deleted file]
tests/sdl-client/ogg/README [deleted file]
tests/sdl-client/packets.c [deleted file]
tests/sdl-client/packets.h [deleted file]
tests/sdl-client/pool.c [deleted file]
tests/sdl-client/pool.h [deleted file]
tests/sdl-client/rawobjs.h [deleted file]
tests/sdl-client/screen.c [deleted file]
tests/sdl-client/screen.h [deleted file]
tests/sdl-client/tests/draw.c [deleted file]
tests/sdl-client/tests/draw.h [deleted file]
tests/sdl-client/tests/fonts.c [deleted file]
tests/sdl-client/tests/fonts.h [deleted file]
tests/sdl-client/tests/msg.c [deleted file]
tests/sdl-client/tests/netrek-like.c [deleted file]
tests/sdl-client/tests/rot.c [deleted file]
tests/sdl-client/tests/snd.c [deleted file]
tests/sdl-client/thread_msg.c [deleted file]
tests/sdl-client/thread_msg.h [deleted file]
tests/sdl-client/thread_net_recv.c [deleted file]
tests/sdl-client/thread_net_recv.h [deleted file]
tests/sdl-client/thread_net_send.c [deleted file]
tests/sdl-client/thread_net_send.h [deleted file]
tests/sdl-client/wav/README [deleted file]
tests/sdl-client/wav/nt_cloaked.wav [deleted file]
tests/sdl-client/wav/nt_explosion_other.wav [deleted file]
tests/sdl-client/wav/nt_fire_torp_other.wav [deleted file]
tests/sdl-client/wav/nt_plasma_hit.wav [deleted file]
tests/sdl-client/wav/nt_shield_down.wav [deleted file]
tests/sdl-client/wav/nt_shield_up.wav [deleted file]
tests/sdl-client/wav/nt_uncloak.wav [deleted file]
tests/zlib/README [deleted file]
tests/zlib/deflate.c [deleted file]
tests/zlib/inflate.c [deleted file]

diff --git a/Xisop/LICENSE b/Xisop/LICENSE
deleted file mode 100644 (file)
index aadb1b9..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/* $Id: LICENSE,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (c) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
diff --git a/Xisop/README b/Xisop/README
deleted file mode 100644 (file)
index 7681f89..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-$Id: README,v 1.7 2004/06/04 02:31:51 mmondor Exp $
-
-
-
-Xisop Copyright 2001-2003, Matthew Mondor,
-All rights reserved.
-
-Currently under development. The only current port is Amiga, and an .uaerc
-is provided for the UAE emulator to test it and possibly enhance it :)
-       Xisop/src/ports/amiga/boot/DOTuaerc
-It is recommended to run the UAE emulator using the -T command line parameter
-when on unix systems (or setting the x11.use_mitshm=true in the ~/.uaerc file).
-Note that kickstart 3.0 or later is required, and that I will not provide this
-file to anyone, as it is copyrighted material. You can buy a kickstart kit, or
-mirror the one of your amiga to file. The models which used to ship with 3.0+
-natively were the A1200 and A4000. It is possible to make Xisop kickstart 1.3
-compatible if it was to be used to make games, since only the bootloader is
-AmigaOS dependent.
-
-The compiled kernel is 30k in size if compiled with statistics support, or
-19k otherwise.
-
-The source of the port-dependent initialization function (which currently
-launches tasks displaying colors for testing and demonstrating) is located at
-       Xisop/src/ports/amiga/boot/init.c
-
-Some development notes are also being worked on according to the internal
-implementation details, programming style notes and how to port Xisop
-(also under development as the kernel interfaces are being stabilized).
-       Xisop/doc/xisop.pdf
-This file is built from xisop.lyx which is maintained using the LyX utility.
-
-Almost all the current code and documentation were re-written from scratch in
-Febuary and March 2003. The old Xisop code somewhat served as reference
-when needed.
-
-Please read TODO on what currently needs to be worked on to continue the
-project, what was done and what needs debugging. The project is to eventually
-be fully released under BSD-style license when at least one port works fine.
-Make sure to also read the documentation in doc/.
-
-To build the amiga port you should specify the location of the cross building
-tools in Xisop/src/ports/amiga/makedefs.sh, or use the defaults if you have
-a NetBSD 1.6.1 source, in which case you can simply use the build.sh script
-provided in /usr/src to build the netbsdelf-m68k target toolchain (which only
-needs to be done once):
-       cd /usr/src
-       ./build.sh -a m68k -t
-Then:
-       cd Xisop/src
-       ./make.sh -t amiga
-
-Matthew Mondor
diff --git a/Xisop/TODO b/Xisop/TODO
deleted file mode 100644 (file)
index 9c2d318..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-$Id: TODO,v 1.20 2004/10/14 15:13:20 mmondor Exp $
-
-
-- Import modifications from mmsoftware/mmlib:
-  - New more efficient pool allocator, with enhanced debugging capability.
-    This could imply reworking some of the whole system.
-  - Maybe incorporate C byteorder library, so that less processor-specific
-    code is required (of course, they can override C ones with asm ones).
-
-
-Working:
-=======
-- Memory management system and ANSI-C related functions
-- Syscalls, including one which allows to execute arbitrary code in supervisor
-       mode
-- Exclusive, recursive and read/write locks
-- User interrupt facilities
-- Preemptive multitasking, _yield() and task_sleep()/task_wakeup()
-- CPU saving ideling
-       When no tasks are on the ready queue to run, the _scontext _ctx_t
-       defined in scheduler.c is resumed, which in fact returns to main.c's
-       main() function, which sole purpose is to sys_idle(), in a loop,
-       which suspends the processor until the next interrupt occurs.
-- Serious exceptions generate a display showing a number of lines which
-  corresponds to the actual error (_ecatch() parameter), useful to debug
-  the current Amiga port.
-- Useful statistics book-keeping of global counters
-- Inter-task signals
-- Inter-task communication reliable ports and messages
-- The init and task reaper system tasks
-- Operations which need fast lookup tables to use kernlib/hash.[ch].
-  This is done for some system lists, such as for port_find().
-- Multiple tasks shareing a common mpool_t created with TF_SHARED
-
-
-Bugs to work out:
-================
-- There again is some problem with memory or stack sizes. When DEBUG and
-  STATISTICS are enabled in config.h, things do not work as intended.
-  This seems to simply arise now that the kernel image is about a k larger.
-  For some reason, the ports/amiga/boot/config.h values do not seem to
-  always generate proper kernel images, for instance when I increase the
-  stack size to 16384 I get a guru meditation...
-- The scheduler which takes task priorities into account is currently not
-  working. There is a temporary replacement scheduler which works now and
-  only performs round-robin when preempting tasks. The old one which has
-  some bugs is found in src/common/kernel/scheduler.c and is called
-  old_schedule().
-- Signals and message ports
-       Some hack should be found a more appropriate solution: signal_send()
-       needs to _yield() twice (See src/common/kernel/signal.c).
-       For some not yet determined reason, tasks would all eventually be
-       stuck on the wait queue if this was not done.
-
-
-Remaining to complete:
-=====================
-- Add system similar to mmlib/mmalarm(3) to Xisop, to go with the existing
-  MI interrupt hook management functions
-- Perhaps use hashtables in exceptions hooks management instead of linked
-  lists? Is this needed or wanted? Running through a hash table is slower,
-  but lookups are faster. Think about it and see which is best to use.
-- Fix issue with amiga port init stack size... m68k usermode() could
-  be specified a stack size for instance, at least. We also could
-  reserve some memory for the stack in advance and supply it...
-- Implement setjmp()/longjmp() for i386
-- CPU specific _bfill16 and _bfill32 etc (at least _bfillint or such),
-  to efficiently fill a native word size with an 8-bit pattern. This
-  could be used by the string library in memset() for instance...
-- Probably that the cases of usecount (devicenode_t, mpool_t) could use
-  an _rlock_t for more efficiency. It is implemented in assembler, and
-  is sure to be atomic.
-- Finish dprintf() FIFO operation optimizations, and write a generic
-  vsnprintf() implementation with stdarg. We want to enhance DPRINTF()
-  to print module and line numbers, etc.
-- _panic()
-- Console and printf() (along with corresponding console.device)
-- Map remaining exceptions to output messages on console
-       For the console.device to eventually exist, the port primitives are
-       essencial. So until they work reliably it's not really possible to
-       implement right now (at least on Amiga).
-       It would be easy to use the video hardware memory on a i386 port
-       however, so a i386 port could perhaps actually help in development
-       for the rest :)
-        Ports implementation is now working reliably. Revise.
-- Probably that the statistics would also be nice to have on a per-task basis.
-       Moreover, they are not as useful as they would if a console existed :<
-       currently, the DPRINTF() system logs to a FIFO buffer.
-- Xisop shared libraries
-- Xisop devices as a synchronization abstraction over the message ports system
-- Xisop handlers as a higher-level (filesystem/file) abstraction over devices
-  libraries and/or hardware
-- Relocatable binary loader
-       This unfortunately either implies writing a full fledged ELF or a.out
-       loader, or a BFD library for GCC ld to output in a new desired format.
-       The ELF loader was started but was not completed (not included in the
-       current sources). ELF unfortunately seems really bloated for the
-       actual needs of this project, and it's state is uncertain.
-       The loader would be used to load shared libraries, and executable
-       tasks, including devices and handlers.
-       For the moment, the system is monolithic and soon a simple interface
-       will be provided to allow the port-specific code to provide a list
-       of tasks to be launched by Xisop init.
-       That alone, even monolithic, allows Xisop to stand as a nice C
-       interface which most code is portable among 32-bit systems, to abstract
-       interrupt facilities, shared memory access and multitasking for
-       various applications. Very small, it can fit the application on a
-       floppy (which includes the kernel).
-- timer.device
-- input.device
-- console.device
-- Add necessary functions to allow linking in the common/kernlib/hash.c module
-
-
-
-NEW MEMORY MANAGEMENT SYSTEM NOTES:
-
-As before, we need several types of memory.
-For each memory type, we should still attach/detach memory chunks, like now.
-
-For each memory chunk, a new system should be implemented for page-level
-contiguous memory management and freeing, as well as a new pool allocator,
-based on the idea of the new mmlib/mmpool(3) one.
-
-Because Xisop does not rely on MMU/PMMU, we can simplify the allocator to a
-simple block allocator, without even worrying about page boundaries, if we
-wanted. This would also mean that a pool page could be virtual, that is, could
-not be dependent on the system page size at all, if we wanted. If that was the
-case, the current mmlib/mmpool(3) allocator could be used as-is.
-
-Not to say that, even if we respected page alignment, we still could use a
-better allocator.
-
-A good idea would be to maintain a list of contiguous page (or memory bytes)
-chunks. Nodes of this list would be split as necessary to provide the
-requested size in the allocation functions. The freeing functions would need
-to attempt to coalesce the contigious chunks together when possible as well.
-
-Perhaps that we also would like a best-fit strategy rather than first-fit when
-allocating, so that we could favor contiguous memory chunks that are closest
-in size to the requested amount, rather than always splitting large chunks
-unnecessarily. This would reduce fragmentation, although being slower at
-allocation. However, because this would affect the page allocator, to which
-calls would be reduced by the pool allocators, this could be reasonable.
-
-Perhaps that to observe the best-fit strategy it would be possible to somewhat
-maintain a sorted index or such, of the smaller to larger available chunks.
-It needs to be verified that the code and memory overhead for such an index
-is negligeable, however. Moreover, would keeping a sorted list of free chunks
-useful for performance? How would the allocator efficiently perform jumps in
-the list? Wouldn't it need to be a tree, instead? If we used one, wouldn't we
-need recursion or special iteration for both node insertion and lookup? I will
-need to check that out. What I should do is count the iterations in my similar
-sorted tree system in dnamed, to get an idea of the actual code overhead
-involved.
-
-struct contiguous_chunk {
-       node_t chunks_node;     /* To link in free/allocated chunks list */
-       node_t sorted_node;     /* To link in free chunks sorted list */
-       void *address;          /* Starting address of free memory */
-       size_t length;          /* Size of contiguous free memory */
-       u_int32_t pages;        /* Or, could be number of free pages */
-};
diff --git a/Xisop/doc/clean.sh b/Xisop/doc/clean.sh
deleted file mode 100755 (executable)
index f4bf49d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# $Id: clean.sh,v 1.2 2004/06/06 04:21:45 mmondor Exp $
-
-rm -f xisop.dvi xisop.tex xisop.lyx~ xisop.pdf xisop.ps xisop.toc .log
diff --git a/Xisop/doc/make.sh b/Xisop/doc/make.sh
deleted file mode 100755 (executable)
index 2300408..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# $Id: make.sh,v 1.3 2004/06/06 04:21:05 mmondor Exp $
-
-# First export LyX document to LaTeX then run this script
-
-lyx -e latex xisop.lyx
-latex xisop.tex
-latex xisop.tex
-rm -f xisop.ps xisop.aux xisop.log .log
-dvips -Pcmz -Pamz -o xisop.ps -t letter -D 300 -Z xisop.dvi
-ps2pdf xisop.ps
-rm -f *~
diff --git a/Xisop/doc/xisop.lyx b/Xisop/doc/xisop.lyx
deleted file mode 100644 (file)
index ad156ca..0000000
+++ /dev/null
@@ -1,10041 +0,0 @@
-#LyX 1.2 created this file. For more info see http://www.lyx.org/
-\lyxformat 220
-\textclass article
-\language english
-\inputencoding auto
-\fontscheme default
-\graphics default
-\paperfontsize default
-\spacing single 
-\papersize letterpaper
-\paperpackage a4
-\use_geometry 1
-\use_amsmath 0
-\use_natbib 0
-\use_numerical_citations 0
-\paperorientation portrait
-\topmargin 0.5in
-\bottommargin 0.5in
-\secnumdepth 3
-\tocdepth 3
-\paragraph_separation indent
-\defskip medskip
-\quotes_language english
-\quotes_times 2
-\papercolumns 1
-\papersides 1
-\paperpagestyle default
-
-\layout Title
-
-Xisop kernel development notes
-\layout Author
-\pagebreak_bottom 
-Copyright (c) 2001-2003, Matthew Mondor
-\newline 
-All rights reserved.
-\layout Standard
-
-
-\begin_inset LatexCommand \tableofcontents{}
-
-\end_inset 
-
-
-\layout Section
-\pagebreak_top 
-General development notes
-\layout Standard
-
-Before attempting to write software for Xisop to expand it's funtionality,
- or before porting Xisop to a new architecture, it is recommended to carefully
- read this manual entirely.
- It attempts to answer all questions one could have about it's organization
- and build process, as well as style and conventions one must follow for
- code consistancy with the rest of the project.
-\layout Subsection
-
-Development software used
-\layout Standard
-
-To develop Xisop, the GNU GCC suite of compiler, assembler, linker and binutils
- software was chosen.
- The main reasons for this consists of cost savings, and portability.
- GCC has support for many different CPU types was a main factor.
- Moreover, the AT&T assembly syntax allows to somewhat obtain some consistency.
-\layout Standard
-
-An effort was made to try to not support GCC-specific functions however,
- for portability reasons.
- For instance, the various 
-\emph on 
-_spl
-\emph default 
-*
-\emph on 
-()
-\emph default 
- functions are implemented as macros around a separate assembly function,
- located in the assembler 
-\emph on 
-.s
-\emph default 
- files, rather than embedded inside the C code using inline assembly directives.
- (
-\emph on 
-XXX
-\emph default 
-\emph on 
-actually they may be fixed to be GCC-dependent soon heh
-\emph default 
-).
-\layout Standard
-
-A choice was made to not use GNU or BSD make.
- Instead, 
-\emph on 
-/bin/sh
-\emph default 
- is assumed to exist.
- This usually consists of a POSIX compliant shell, on GNU systems (and Linux)
- the 
-\emph on 
-bash
-\emph default 
- shell usually emulates it's behavior and 
-\emph on 
-/bin/sh
-\emph default 
- then consists of a symbolic link to 
-\emph on 
-/bin/bash
-\emph default 
-.
- On BSD systems only POSIX 1003.2 and 1003.2a functionality is usually present
- in their 
-\emph on 
-/bin/sh
-\emph default 
-, which is what Xisop build scripts are making use of.
- As
-\emph on 
-\emph default 
-such,
-\emph on 
- bash
-\emph default 
- is therefore not a requirement.
-\layout Standard
-
-This document is written and maintained using LyX.
- The UAE (Amiga emulator) and Bochs (i386 emulator) utilities were useful
- to develop the current ports.
- The original host development system consists of an i386 compatible system
- running NetBSD 1.6_STABLE.
- This operating system is ideal for programming and cross compiling.
- The current Xisop building system was tuned to the NetBSD 1.6.1 toolchain.
- To compile the amiga port, for instance, you only should need to use the
- build.sh script to build the suite of netbsdelf-m68k tools.
- Using the Xisop 
-\begin_inset Quotes eld
-\end_inset 
-
-
-\emph on 
-./make.sh -t amiga
-\emph default 
-
-\begin_inset Quotes erd
-\end_inset 
-
- command should then build the amiga target.
-\layout Standard
-
-The software was written using the VIm editor, with 
-\emph on 
-ts=8
-\emph default 
-, 
-\emph on 
-sw=4
-\emph default 
- and 
-\emph on 
-cindent
-\emph default 
-.
-\layout Standard
-
-If you compile your own gcc with your intended compiling target, you simply
- need to change a file to tell the locations of the various building tools.
- See the section about 
-\begin_inset Quotes eld
-\end_inset 
-
-the build process
-\begin_inset Quotes erd
-\end_inset 
-
- later on for more information.
-\layout Subsection
-
-Xisop compatibility with other systems, and where it fits best
-\layout Subsubsection
-
-UNIX, POSIX, BSD, Linux
-\layout Standard
-
-Xisop is definitely not POSIX, although it's functions are simpler than
- POSIX is, requireing a small learning curve only to use.
- It was not designed as a general-purpose operating system to replace Unix
- and provide all it's capabilities.
- It's an entity of it's own, simpler and smaller, mostly made to suit the
- requirements of restricted embedded systems.
- To implement most POSIX requirements a larger system is required, which
- generally also results in slower code.
- For instance, Xisop addresses ports and tasks as addresses, rather than
- IDs.
- This solves the problem of allocation and reuse of process IDs.
-\layout Standard
-
-A Xisop task also is lightweight compared to a UNIX-style process.
- Moreover, the need for more custom user signals than POSIX environment
- provides made it unsuitable to reserve almost all 32 signals to reserved
- semantics.
- The concept of file descriptors and select()/poll() is also different.
- However, SIGPOLL signal was reserved in Xisop for the implementation of
- message-based signals and events using a single message port and signal.
- This can be used when there can be a large number of entities a task may
- be monitoring, and the user signals would not be appropriate.
- It would be possible to work a system out using this facility for the 32
- standard Unix signals if the need existed.
-\layout Standard
-
-Although it would be possible to implement POSIX compatibility libraries,
- it was not a main goal in Xisop development.
-\layout Subsubsection
-
-Memory and process protection
-\layout Standard
-
-Xisop was not designed to support Memory Management Unit (MMU) coprocessors
- and provide page-grained memory protection.
- This helped to implement message passing in a very efficient manner, only
- passing pointers around, and reduced considerably kernel size.
- Moreover, it allows to provide most user-access system functions in a shared
- library, reducing considerably the amount of system calls an application
- needs to make (accessed through traps).
- The number of traps being reduced, the preemtive scheduler is less clobbered.
- Calling functions of a shared library happen entirely in the caller's task
- allocated CPU time slice, which means that the kernel load is not affected.
- Not requireing MMU is also an advantage with Xisop, as it can run with
- a single MC68000L8 for instance, and a little RAM.
-\layout Standard
-
-However, we all know that without appropriate memory protection, Xisop cannot
- efficiently protect the kernel from user tasks, which can take full control
- on the system at any time.
- Clean interfaces were however implemented, which internally perform various
- sanity checking to ensure the validity of the supplied objects and arguments,
- so that common software bugs do not automatically corrupt memory and the
- system.
- Xisop knows the difference between a valid task, port, device handle, etc,
- and invalid ones.
- It also knows when to not attempt to free memory if a wrong pointer is
- supplied, since 
-\emph on 
-mnode_t
-\emph default 
- nodes are also validated using a unique magic cookie.
- Such steps permit to minimize system crashes in the event of a software
- bug.
-\layout Standard
-
-The kernel comports special macros to aid in realizing object validity sceals
- and dependancies checking, which are defined in <
-\emph on 
-common/kernel/object.h
-\emph default 
->:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-OBJECT_VALIDATE(objptr,\SpecialChar ~
-objtype)
-\emph default 
- Sets the 
-\emph on 
-objptr
-\emph default 
-->object_magic field to 
-\emph on 
-objtype
-\emph default 
-.
- This type corresponds to one of the 
-\emph on 
-OBJECT_
-\emph default 
-* names which are defined in the same headerfile.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-OBJECT_INVALIDATE(objptr)
-\emph default 
- Sets the 
-\emph on 
-objptr
-\emph default 
-->object_magic field to 0.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-OBJECT_REGISTER(objptr)
-\emph default 
- Registers 
-\emph on 
-objptr
-\emph default 
- object by setting the 
-\emph on 
-objptr
-\emph default 
-->object_id field to a unique number.
- This number will be used for matching when verifying for proper dependancy
- link.
- Only objects which may be required as dependancy to others need to use
- this.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-OBJECT_SETDEP(objptr,\SpecialChar ~
-depobjptr)
-\emph default 
- Associates 
-\emph on 
-objptr
-\emph default 
- object as requireing the 
-\emph on 
-depobjptr
-\emph default 
- object as dependancy for proper function.
- What this does is internally set 
-\emph on 
-objptr
-\emph default 
-->objdep_magic to 
-\emph on 
-depobjptr
-\emph default 
-->magic and 
-\emph on 
-objptr
-\emph default 
-->objdep_id to 
-\emph on 
-depobjptr
-\emph default 
-->object_id.
- As a result, it becomes possible to refuse to perform operations related
- to this object if the dependancy link ever dies.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-OBJECT_VALID(objptr,\SpecialChar ~
-objtype)
-\emph default 
- First verifies if objptr is non-NULL, and then evaluates if the object
- associated with 
-\emph on 
-objptr
-\emph default 
- truely corresponds to 
-\emph on 
-objtype
-\emph default 
- (
-\emph on 
-objptr
-\emph default 
- != NULL && 
-\emph on 
-objptr
-\emph default 
-->object_magic == 
-\emph on 
-objtype
-\emph default 
-).
- This consists of the reason why the various 
-\emph on 
-OBJECT_
-\emph default 
-* definitions in the headerfile should consist of unique values which are
- unlikely to occur randomly.
- Returns TRUE on success, or FALSE otherwise.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-OBJECT_DEPENDS(objptr,\SpecialChar ~
-depobjptr)
-\emph default 
- Verifies the integrity of a dependancy link, which was previously linked
- using 
-\emph on 
-OBJECT_SETDEP()
-\emph default 
- on 
-\emph on 
-objptr
-\emph default 
-.
- This in fact makes sure that the object it should relate to (
-\emph on 
-depobjptr
-\emph default 
-) is still valid, and consists of the same one (
-\emph on 
-depobjptr
-\emph default 
- != NULL && 
-\emph on 
-depobjptr
-\emph default 
-->object_magic == 
-\emph on 
-objptr
-\emph default 
-->objdep_magic && 
-\emph on 
-depobjptr
-\emph default 
-->object_id == 
-\emph on 
-objptr
-\emph default 
-->objdep_id).
- Returns TRUE on success, or FALSE otherwise.
-\layout Standard
-
-Obviously, the structure of an object only requires to hold the fields which
- are required for the functionality it requires according to these macros.
- Those fields are all expected to be of type 
-\emph on 
-u_int32_t
-\emph default 
-.
- This system allows relatively lightweight validity checking of object credentia
-ls, without the need for memory protection.
- The kernel uses them wherever needed for safety.
- Using this system also allows to use efficient dynamic memory allocation
- techniques (
-\emph on 
-pool_t
-\emph default 
- functions) to create and destroy critical system objects, and reference
- can be made using pointers through the system, rather than using less efficient
- or fixed-sized arrays and object ID allocation.
- Programming using these macros also yields in a clean interface to result
- in consistant, clean C code.
-\layout Subsubsection
-
-Multitasking
-\layout Standard
-
-While Xisop provides preemptive multitasking (more information provided
- in the next section), it can be disabled by user applications if need be.
- This means that Xisop can be used to create single-tasking applications
- where a multitasking environment is not wanted, while still taking advantage
- of the abstraction of CPU and hardware access Xisop allows.
- This for instance allows games to be written almost entirely in C, and
- be independent of an operating system such as Windows or AmigaOS, using
- Xisop instead.
- Such a small game can be booted from a single floppy, which would comport
- all necessary components of the game, including Xisop itself.
- Disabling multitasking also allows direct access to the hardware resources
- by the main application, in a safe manner.
- When multitasking is enabled, such safe access to hardware resources is
- also provided, although using the 
-\emph on 
-device
-\emph default 
- concept is required to remain multitasking friendly and access those.
- More information about Xisop devices is given later on.
-\layout Standard
-
-This means that multitasking was provided as a useful optional facility
- rather than to force limits over the applications.
- It is great to develop some kinds of systems using multitasking, while
- some other applications are much better without it.
- This was an important consideration when designing Xisop.
- Whether multitasking is enabled or disabled, the public interrupt facilities
- interface works as expected.
- More information is provided on this interface in a later section.
-\layout Subsubsection
-
-AmigaOS
-\layout Standard
-
-Although some ideas were admitedly borrowed from the Amiga Operating System,
- the compatibility stops there.
- The AmigaOS headerfiles, although publically available, or source code
- (which is unavailable publically) were not used as a reference to write
- it, nor can Xisop run AmigaOS native object files and binaries.
- Xisop is a clean-room kernel implementation, written from scratch and uses
- it's own set of ideas and conventions, which are described in this document.
-\layout Standard
-
-The Xisop signals, message ports, devices and handlers concepts were however
- borrowed from AmigaOS, as it was a great proof of feasibility using a very
- simple underlaying structure.
- The interface and internals do not behave identically but anyone who programmed
- using the AmigaOS inter-task communication and synchronization features
- will feel at ease with Xisop.
-\layout Subsubsection
-
-Where Xisop fits best
-\layout Standard
-
-The best application Xisop suits for consists of an embedded system, dedicated
- to provide specific services or tasks, running with low-cost hardware and
- restricted physical memory.
- There are however a wide range of applications which fit in this category,
- cell phones, microwave ovens, PDAs, clocks, industrial microcontrollers
- or event loggers, alarm systems, etc.
- An example of low-cost hardware Xisop runs great on is a Motorola MC68000L8
- microprocessor based board with a restricted 512 kilobytes of memory, and
- an RS-232 interface with UART controler chip.
- Xisop can also be used to develop games on 32-bit consoles or arcade hardware.
-\layout Standard
-
-Xisop consists of a nice component when simplifying hardware design of a
- project, where a simple CPU unit, little RAM and Xisop-based software can
- provide the tasks of more complex hardware-only solutions.
- This also implies that the simpler hardware may then be reused, since it
- now basically consists of a general purpose programmable system rather
- than single-purpose hardware units which can only serve for a single project.
-\layout Standard
-
-It does not consist of a full multipurpose operating system but rather of
- a collection of primitives to aid a C programmer to write his applications
- on a variety of hardware, and benefit from memory management including
- support for runtime dynamic memory addition and removal, as well as multiple
- memory types, inter-task communication primitives, a fair number of user
- signals, abstracted interrupt facilities, and a microkernel design allowing
- to add future functionality modularized as userspace tasks, shared libraries,
- devices and handlers.
-\layout Standard
-
-It's weak license (BSDL-style) makes it especially suitable for commercial
- embedded applications when a technical team can build a custom application,
- where royalties for use, or redistribution of custom changes in the code
- are not required.
- An effort is provided to make the CPU-specific interface abstract so that
- most of the code can be written in C, for code clarity, consistency, developmen
-t speed and ease.
- The assembly code is restricted to the minimum, and always consists of
- a backend to use C.
- The same is true for architecture-specific assembly low-level code.
- Those sections are described later on.
-\layout Standard
-
-As such, very little time is generally required to port the basics of Xisop
- to a new architecture (other 32-bit ones, at least).
- Engineers can then develop custom low-cost hardware and a programmer can
- write most of the software for it using C and Xisop rather than having
- to write all of it in assembly, or starting from nothing and having to
- re-invent the assembly to C support primitives.
-\layout Standard
-
-Very low cost hardware helps when many units are being deployed.
- However, in the cases where the hardware costs are higher (i.e.
- microprosessor with MMU support and 8 or more megabytes of memory), Xisop
- may seem too rudimentary, but there are then alternatives such as NetBSD
- which can be ported quite fast (when required, as it already consists of
- the most portable OS), and POSIX functionalities, with full unix features,
- networking, protected memory, etc all become available.
- It is also released under the BSD unrestrictive license and is available
- at 
-\emph on 
-http://www.netbsd.org
-\emph default 
-.
-\layout Subsection
-
-Xisop coding standards
-\layout Subsubsection
-
-Licencing issues and censorship
-\layout Standard
-
-All code which is to be publically released within the standard Xisop distributi
-on should be licensed under a BSD-style license, and should not be released
- under the GNU Public License (GPL) or GNU Lesser Public License (LGPL).
- It however is obvious that companion packages be released and distributed
- separately with the Xisop main archive, as long as it be clearly isolated
- and labeled as such, so that it can easily be stripped when code under
- such strict a license is not wanted within a project.
- It is allowed for authors to include their advertizing clause as wanted
- in the BSD license advertizing at the top of their files.
- A main file can then easily be created using a script of advertizement
- clauses and related files whcih one can append in the documentation of
- a commercial or closed source product using Xisop.
-\layout Standard
-
-This allows anyone to use Xisop for open source or closed source projects
- as wanted.
- Although it is encouraged to publically donate the new processor and architectu
-re specific modules one develops, as well as machine-independent new modules
- of interest for inclusion into the main Xisop tree, released under BSD
- license, noone is obliged to do so.
- This also allows the main tree to not become too tainted with alot of code
- everyone develops which does not serve the other Xisop users much and mostly
- bloat the project.
- The mirokernel design easy allows third party supplied libraries, devices
- and handlers to be developed, and these may also be closed source, and
- commercial.
- There of course is no problem to release such optional kernel-independent
- modules under one of the GNU licenses.
-\layout Standard
-
-If you port Xisop to a new processor or architecture, and are willing to
- contribute the code to the tree, I suggest that the source be obtained
- via CVS from the main Xisop source repository, and that 
-\emph on 
-cvs diff -u
-\emph default 
- be used to create a patch.
- This patch should be sent via email to Matthew Modor, at 
-\emph on 
-mmondor@gobot.ca
-\emph default 
-.
- I then will attempt to merge it into the main Xisop CVS tree, after performing
- basic sanity checking on the code, and fixing required bugs if possible
- (if any).
- I may also reply back if there is any reason why the changes cannot be
- applied, in which case I could help to make it conform with the requirements.
-\layout Subsubsection
-
-Standard data types and when to use them
-\layout Standard
-
-Xisop uses a defined set of data types in it's kernel, and attempts to remain
- consistant when using them for code clarity and obviousness.
- The following C standard data types are used:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-char
-\emph default 
- The standard C character type, used for C strings only in Xisop.
-\emph on 
-int8_t 
-\emph default 
-and
-\emph on 
- u_int8_t
-\emph default 
- should be used for other byte-related types.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-char\SpecialChar ~
-*
-\emph default 
- Obvious, also only used in direct relation with C strings.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void
-\emph default 
- When a function returns nothing, or has no arguments, for both prototype
- and function declaration.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*
-\emph default 
- This consists as usual, of a pointer to an abstract type, and is used where
- required.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-int
-\emph default 
- This is used as a convenient format for various return codes and variables
- where bit-size is not a concern, or should match the one which is assumed
- for the processor (although it is highly recommended to use the various
- defined types below for these).
-\layout Standard
-
-The other standard C data types are replaced by the following ones, which
- are defined in the Xisop machine-independent <
-\emph on 
-common/types.h>
-\emph default 
- headerfile:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool
-\emph default 
- Corresponds to 
-\emph on 
-int
-\emph default 
-, but specifically denotes that this variable is used for boolean operations
- and conditionals for code clarity it may only hold TRUE (1) or FALSE (0)
- values.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-int8_t
-\emph default 
- Is used everywhere byte-sized signed elements are explicitely required,
- from -127 to +128, except for strings where the standard C 
-\emph on 
-char
-\emph default 
- type should be used.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-u_int8_t
-\emph default 
- Should be used where unsigned byte-sized elements are required, for 0-255
- values.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-int16_t
-\emph default 
- Is the data type used for 16-bit signed integers values, -32768 to +32767.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-u_int16_t
-\emph default 
- The unsigned 16-bit value data type which can old 0 to 65535.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-int32_t
-\emph default 
- For use with 32-bit signed data types
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-u_int32_t
-\emph default 
- 32-bit unsigned data type
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-int64_t
-\emph default 
- signed 64-bit data type (usually typedef with 
-\emph on 
-long long
-\emph default 
-)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-u_int64_t
-\emph default 
- unsigned 64-bit data type.
- It is to be noted that operations on 64-bit objects is generally slow as
- it requires multiple instructions on 32-bit architectures.
- Currently, no 64-bit data types are beign used anymore, the few ones which
- used it were converted to use 32-bit ones instead.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-size_t
-\emph default 
- Used to represent a size in bytes, this in fact is equivalent to 
-\emph on 
-u_int32_t
-\emph default 
-.
-\emph on 
-size_t
-\emph default 
- should not be used to represent arbitary types amounts, but byte amounts
- only (corresponding to a number of 
-\emph on 
-char
-\emph default 
-, 
-\emph on 
-u_int8_t
-\emph default 
- or 
-\emph on 
-int8_t
-\emph default 
- types).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-ssize_t
-\emph default 
- Purpose is the same as for 
-\emph on 
-size_t
-\emph default 
-, but this can hold -1 for error.
-\layout Standard
-
-And other frequently used standard Xisop types, which are still defined
- in <
-\emph on 
-common/types.h
-\emph default 
->, but have their corresponding structures defined at their respective locations
- (mentionned in parentheses):
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-node_t
-\emph default 
- A doubly linked list node to be used in 
-\emph on 
-list_t
-\emph default 
- type lists.
- (common/kernlib/list.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-list_t
-\emph default 
- A doubly linked list (common/kernlib/list.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-mchunk_t
-\emph default 
- A chunk of contiguous memory pages, part of a 
-\emph on 
-ppool_t
-\emph default 
- (common/kernel/memory.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-page_t
-\emph default 
- A physical memory page, or a number of contiguous physical memory pages,
- holding the necessary information for freeing back.
- (common/kernel/memory.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-ppool_t
-\emph default 
- A system pool of pages, that is, what other pools allocate pages from.
- (common/kernel/memory.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-pool_t
-\emph default 
- A efficient fixed sized objects (
-\emph on 
-pnode_t
-\emph default 
-) memory pool with internal statistical page cacheing, which can optionally
- dynamically grow and shrink, or be static in size (common/kernel/memory.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-pnode_t
-\emph default 
- A pool object node, which must prefix any pool object.
- This type internally begins with a 
-\emph on 
-node_t
-\emph default 
- and can therefore be used directly for queuing in 
-\emph on 
-list_t
-\emph default 
-.
- (common/kernel/memory.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-mpool_t
-\emph default 
- A multiple 
-\emph on 
-pool_t
-\emph default 
- memory pool used to serve multiple sized blocks requests.
- Of various memory types.
- Bocks which are too large are rounded at page boundaries.
- (common/kernel/memory.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-mnode_t
-\emph default 
- Internally used by the 
-\emph on 
-mpool_t
-\emph default 
- related allocation primitives (common/kernel/memory.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-facility_t
-\emph default 
- A public interrupt facility which the port-specific code initializes calling
- the common 
-\emph on 
-facility_init()
-\emph default 
- function.
- (common/kernel/exception.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-hook_t
-\emph default 
- An interrupt, trap or exception code vector attached to a 
-\emph on 
-facility_t
-\emph default 
-.
- (common/kernel/exception.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-hookid_t
-\emph default 
- An 
-\emph on 
-hook_t
-\emph default 
- ID, internally a 
-\emph on 
-u_int32_t
-\emph default 
-, which is guarranteed to be unique for the facility it belongs to.
- (common/kernel/exception.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-task_t
-\emph default 
- Task structure (common/kernel/task.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-priority_t
-\emph default 
- A task priority number (common/kernel/task.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-signum_t
-\emph default 
- Signal number (common/kernel/signal.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-sigmask_t
-\emph default 
- Signal mask which can represent one or more 
-\emph on 
-signum_t
-\emph default 
-.
- (common/kernel/signal.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-port_t
-\emph default 
- Message port (common/kernel/port.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-message_t
-\emph default 
- A message header structure which comports the glue to queue messages in
-\emph on 
-port_t
-\emph default 
- (common/kernel/port.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-device_t
-\emph default 
- An open device handler (common/kernel/device.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-devicenode_t
-\emph default 
- A linked device hook (common/kernel/device.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-iorequest_t
-\emph default 
- An I/O request message type used for 
-\emph on 
-device_t
-\emph default 
- requests (common/kernel/device.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-fifo8_t
-\emph default 
- An 8-bit elements FIFO buffer.
-\emph on 
-fifo
-\emph default 
-*
-\emph on 
-_t
-\emph default 
- types are implemented as a fixed bytes buffer once initialized, rather
- than using linked lists.
- It is possible to easily create new 
-\emph on 
-fifo
-\emph default 
-*
-\emph on 
-_t
-\emph default 
- types of arbitrary object sizes using a macro.
- (common/kernlib/fifo.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-fifo16_t
-\emph default 
- A 16-bit elements FIFO buffer (common/kernlib/fifo.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-fifo32_t
-\emph default 
- A 32-bit elements FIFO buffer (common/kernlib/fifo.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-lifo8_t
-\emph default 
- A 8-bit elements LIFO buffer.
-\emph on 
-lifo
-\emph default 
-*
-\emph on 
-_t
-\emph default 
- types operate like stacks, and are internally implemented as a fixed bytes
- buffer once initialized, rather than using linked lists.
- A macro is provided to easily create new types of 
-\emph on 
-lifo
-\emph default 
-*
-\emph on 
-_t
-\emph default 
- for objects of arbitrary size.
- (common/kernlib/lifo.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-lifo16_t
-\emph default 
- A 16-bit elements LIFO buffer (common/kernlib/lifo.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-lifo32_t
-\emph default 
- A 32-bit elements LIFO buffer (common/kernlib/lifo.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-hashtable_t
-\emph default 
- A hash lookup table (common/kernlib/hash.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-hashnode_t
-\emph default 
- A hash lookup table node (common/kernlib/hash.h>
-\layout Standard
-
-And here are the processor and architecture specific opaque data types they
- provide:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_ipl_t
-\emph default 
- Abstract Interrupt Priority Level type, associated with the 
-\emph on 
-_spl
-\emph default 
-n
-\emph on 
-()
-\emph default 
- and 
-\emph on 
-_splx()
-\emph default 
- functions.
- (processor/support.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_ctx_t
-\emph default 
- Abstract processor-specific supplied context handle, associated to 
-\emph on 
-_ctx_init()
-\emph default 
- function which is used by 
-\emph on 
-task_alloc()
-\emph default 
- and internal kernel context switching.
- (processor/support.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_lock_t
-\emph default 
- Abstract processor-specific supplied atomic simple lock handle.
- Associated to the 
-\emph on 
-_lock_
-\emph default 
-*
-\emph on 
-()
-\emph default 
- functions.
- (processor/support.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_rlock_t
-\emph default 
- An abstract atomic recursive lock handle (needs to be unlocked the same
- number of times it was locked to free the 
-\emph on 
-_rlock_t
-\emph default 
-).
- Associated to the 
-\emph on 
-_rlock_
-\emph default 
-*
-\emph on 
-()
-\emph default 
- functions.
- (processor/support.h)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-XXX
-\emph default 
- The 64-bit related types are currently unused.
- On most processors the GCC compiler requires additional libraries to support
- these, which are currently not part of Xisop.
- There however exist such implementations fully written in C, like the one
- used on BSD systems which would not be hard to include if it was necessary.
- An effort was made to also not include software which requires the use
- of floating point, for code size and efficiency.
-\layout Subsubsection
-
-Programming style and conventions
-\layout Standard
-
-It is a fact that consistency is a must for readibility, especially in an
- open source project which many others may need to modify to suit their
- particular needs.
- The following programming conventions are used, and are defined for assembly
- and C code.
-\layout Paragraph
-
-Function names
-\layout Standard
-
-All functions which are not behaving identically to ANSI-C or POSIX or other
- widely standarized ones, but have the same name should have their name
- prefixed by an underscore ('_').
- Others which behave exactly like the standards should have the same name
- the standard expects.
- Other functions which have nothing in common with standard names should
- not be prefixed by underscores, except for the defined processor and port-speci
-fic functions, which names should also begin with an underscore.
- Of course, if a hardware-specific function is provided as a replacement
- to a common portable one for performance considerations, it obviously should
- bear the same name, however.
-\layout Paragraph
-
-Formatting
-\layout Standard
-
-Line termination should consist of 
-\begin_inset Quotes eld
-\end_inset 
-
-
-\backslash 
-n
-\begin_inset Quotes erd
-\end_inset 
-
- (linefeed, as is used on Amiga and Unix), rather than 
-\begin_inset Quotes eld
-\end_inset 
-
-
-\backslash 
-r
-\backslash 
-n
-\begin_inset Quotes erd
-\end_inset 
-
- which is used on MS-DOS and Windows for text file storage.
- Other than tab (
-\begin_inset Quotes eld
-\end_inset 
-
-
-\backslash 
-t
-\begin_inset Quotes erd
-\end_inset 
-
-) and linefeed (
-\begin_inset Quotes eld
-\end_inset 
-
-
-\backslash 
-n
-\begin_inset Quotes erd
-\end_inset 
-
-), no other control characters should be found within the source files.
- Moreover, every line of the source files should not exceed 79 characters.
-\layout Paragraph
-
-C language sections
-\layout Standard
-
-It is important that C files be using the standard eight (8) tab size for
- real tabs.
- However, the software tab should consist of four (4) characters.
- Tabs should be used where 8 space tabs are needed, and spaces used to fill
- the 4 character tabs.
- When using the VIm editor, these should be used: 
-\emph on 
-ts=8
-\emph default 
-, 
-\emph on 
-sw=4
-\emph default 
-, and 
-\emph on 
-cindent
-\emph default 
-.
- This allows the files to be printable using text file viewers properly
- at all times, and to also be printable as-is on most printers.
-\emph on 
-XXX
-\emph default 
- Add settings for emacs
-\layout Itemize
-
-C program suffix should consist of lower case 
-\emph on 
-.c
-\layout Itemize
-
-C headerfiles should use the lower case suffix 
-\emph on 
-.h
-\layout Itemize
-
-ANSI-C programming norms should be observed as much as possible.
-\layout Itemize
-
-ANSI convention for function arguments specification rather than K&R.
-\layout Itemize
-
-BSD programming style used rather than GNU style, especially for opening
- and closing braces convention.
- This corresponds to the formatting performed using GNU indent program with
- the following parameters: 
-\emph on 
-gindent -kr -ncs <file>.c
-\layout Itemize
-
-Functions and global variables which are specific to the current module
- should be declared 
-\emph on 
-static
-\emph default 
-, and their prototypes should be in a private headerfile or in the current
- C source file, not in a public headerfile which is included by any other
- C source module.
-\layout Itemize
-
-Macros and variables directly refering to hardware architecture-specific
- registers should use the 
-\emph on 
-volatile
-\emph default 
- keyword.
-\layout Itemize
-
-Every function must have a corresponding prototype, defined either at the
- top of the current C file (if static) or in a corresponding headerfile
- (public ones).
-\layout Itemize
-
-For kernel code, the conventions should be followed about the choice of
- variable types to use (described in the previous section).
-\layout Itemize
-
-No C++ or other language should be used within the kernel code.
- Of course there is no such restriction for any user program.
-\layout Itemize
-
-Code should obviously be commented as required for clarity, but 
-\emph on 
-
-\begin_inset Quotes eld
-\end_inset 
-
-/*
-\begin_inset Quotes erd
-\end_inset 
-
-
-\emph default 
- and 
-\emph on 
-
-\begin_inset Quotes eld
-\end_inset 
-
-*/
-\begin_inset Quotes erd
-\end_inset 
-
-
-\emph default 
- C-style delimited comments only are allowed, not 
-\emph on 
-
-\begin_inset Quotes eld
-\end_inset 
-
-//
-\begin_inset Quotes erd
-\end_inset 
-
-
-\emph default 
- C++ ones.
-\layout Itemize
-
-Code should not invoke general purpose memory allocation routines when a
- special fast access pool was provided already to allocate and free these
- types of items.
- Where appropriate, the general kernel objects pool system should be expanded
- when a new object is frequently allocated and freed, rather than using
- the general purpose management functions.
- These obviously should be common, machine-independent objects (which can
- possibly use machine-specific definitions, if they become standard and
- documented in this document so all ports provide them).
- See the memory management section later on for more information.
-\layout Itemize
-
-General purpose libraries supplied in 
-\emph on 
-src/common/kernlib/
-\emph default 
- should normally have each function implemented as a separate C file into
- the library's directory.
- During the build process they will get compiled independently, and then
- archived together using 
-\emph on 
-ar
-\emph default 
-.
-\emph on 
-ranlib
-\emph default 
- will then be executed on the archive.
- This ensures that unused functions do not be included into the end kernel
- result, reducing kernel size considerably when full multipurpose libraries
- are used (such as complete string libraries).
-\layout Paragraph
-
-Assembly sections
-\layout Standard
-
-For assembly sections, the AT&T style should be observed, and the assembly
- should not be embedded into the C code using inline assembly routines.
- Often a library requireing both assembly and C will at build time assemble
- it's assembly section file (
-\emph on 
-.s
-\emph default 
-), compile it's C part (
-\emph on 
-.c
-\emph default 
-), and link the two together into an object file (
-\emph on 
-.o
-\emph default 
-) using the 
-\emph on 
--r
-\emph default 
- linker switch, which then gets linked with the kernel.
- In other situations one may want to instead compile all modules to objects
- (
-\emph on 
-.o
-\emph default 
-), create an 
-\emph on 
-ar
-\emph default 
- archive (
-\emph on 
-.a
-\emph default 
-), run 
-\emph on 
-ranlib
-\emph default 
- on it, and link it to the kernel (in which case all unused functionality
- which was isolated into it's own module does not get included by the linker,
- reducing kernel size).
- This applies to both processor-specific and architecture-specific backends.
- The rest is written in C.
- It is encouraged to write most of the architecture-specific boot loader
- code in C and provide a companion assembly file to interface and call the
- C loader main function.
- This minimizes assembly code, and C is more consistant and readable, it
- can be more suitable to sometimes write tricky sections like relocators,
- etc.
-\layout Standard
-
-The assembly sections should ensure to be reeintrant, that is, using the
- stack to save registers rather than using temporary registers to save other
- registers, and using the stack as well for temporary variables for which
- registers cannot be used, rather than static memory locations.
- These are usually indended to be called from C, and because of the way
- Xisop shared libraries work, is a main reason to follow these directives.
- An assembly section which is known to execute uninterruptably may at it's
- discretion use static memory if needed.
-\layout Itemize
-
-Assembly files should have the following lowercase suffix: 
-\emph on 
-.s
-\layout Itemize
-
-Tabulation should be set to use real tabs (not spaces), with a standard
- tab width of 8.
-\layout Itemize
-
-Assembler opcodes should be located after the first tab.
-\layout Itemize
-
-Operands should be located after the second tabulation.
-\layout Itemize
-
-Where more than an operand is required and are separated by a comma, a space
- is required after the comma.
-\layout Itemize
-
-Opcode names should be lowercase, and must match those shown by objdump
- when dissassembling.
- This allows consistancy between all code for a particular processor.
- Although this may sound tidious at first, it is not as hard as it sounds
- to learn the specific mnemonic names objdump displays, with some little
- practice.
- Adventages results in consistency, where it also becomes possible to locate
- specific instructions in the code with regular expressions, etc.
-\layout Itemize
-
-
-\emph on 
-.equ
-\emph default 
- and 
-\emph on 
-=
-\emph default 
- directives, if any, should be located at the top of the assembly file.
-\layout Itemize
-
-
-\emph on 
-.globl
-\emph default 
- directives to declare public functions should also be located at the top
- of the file.
-\layout Itemize
-
-All code should be within the 
-\emph on 
-.text
-\emph default 
- section, along with any static memory variables if need be (although use
- of these is discouraged, except for instance in the kernel loader bootblock
- where they can be useful, or in special context code where one knows what
- he's doing rather than only using the stack).
-\layout Itemize
-
-A comment on a line or two should be placed before each function, especially
- the ones which are intended to be called from C, along with the C prototype.
-\layout Itemize
-
-Other comments should be found along the code where required for obviousness.
-\layout Itemize
-
-Obviously, registers which a function modifies should be saved in the stack,
- and restored upon function return, except (if any) the register corresponding
- to the return code expected in C for that processor.
-\layout Itemize
-
-Interrupt, trap and exception assembly sections should normally save all
- registers which are commonly used for the particular processor, and restore
- them before returning.
- It is wrong to assume that C compiled functions always save all registers
- they modify other than the expected result register.
- This was learned from experience using GCC.
-\layout Subsection
-
-Xisop scheduler and inter-task communication
-\layout Subsubsection
-
-The multitasking scheduler
-\layout Standard
-
-The scheduler currently allows to set priorities for each task, between
- -128 and 127.
- It is preemptive and will make sure to allow other tasks to run even when
- a particular task hugs the CPU by not going to sleep.
- A task can be in two main states: running, and sleeping.
-\layout Standard
-
-When a task sleeps, it has a mask of signals that will awake it as soon
- as possible if it receives any signal it waits for, and leaves more opportuniti
-es for other tasks to execute their shores when it is sleeping.
- When a task runs, it usually executes it's shores and goes back to sleep
- for the next event to process, when running in a multitasking system.
- However, if it does not return to sleep fast enough, the scheduler preemtive
- nature will suspend it and allow other tasks to also get a fair CPU time
- share, depending on the priority of the running tasks, unless the task
- has disabled scheduling, in which case it will remain running until it
- decides to delegate control to the system again.
-\layout Standard
-
-The task priority controls the speed and frequency at which a running task
- awakes, or runs.
- What the scheduler does is assign a set of credits to all tasks in the
- run queue, according to their priority one another.
- Then using round-robin at each scheduler round, the task with the highest
- amount of credits is given some CPU time, and a credit is taken out from
- it.
- If a task expired it's credits, it is no longer given a round, until all
- other tasks also expired their credits.
- When this happens, all tasks are given credits according to their priority
- again.
- Some care is taken to not constantly give a turn to the last task even
- if it has more credits, to allow to make the best out of Xisop asynchroneous
- facilities, but such a high priority task will have more turns within the
- run still, observing it's relative priority to the others.
-\layout Standard
-
-When a task goes to sleep, it is immediately taken out of the run queue
- and will not be awaken until a signal it awaits for is received.
- When it does, it will be moved in the running queue as fast as possible,
- at which point the time elapsing before it can act to the signal is directly
- dependent on the priority of the task related to the other ready to run
- tasks.
- However, when the task is moved in the run queue, it is immediately given
- it's credits at the maximum it's priority permits, thus increasing the
- chances it can answer in a fast manner among the other tasks in the run
- queue, which may already have been there before, and elapsed their credits.
-\layout Standard
-
-This means that if all tasks run with the default priority of 0, they all
- get a fair share of the CPU, and are naturally awaking very fast when one
- get a signal.
- In the case where one of the tasks remains running, the speed of signal
- responsiveness will ususally consist of the frequency of the scheduler.
- This frequency is usually configurable, and depends on the capacity of
- the timers available for the particular architecture (and of course on
- CPU speed).
-\layout Standard
-
-In the case where the scheduler detects that all tasks are sleeping, it
- attempts to reduce it's CPU usage by calling the 
-\emph on 
-_idle()
-\emph default 
- processor-specific function, which will only awaken the scheduler again
- when the next interrupt, trap or exception occurs.
- It is possible in Xisop to have dead locked tasks, if they decide to wait
- for no signals, or if they wait for a signal to occur which never does.
-\layout Standard
-
-Following are described all functions which are related to tasks and scheduler,
- or which are useful to synchronize resources, other than the 
-\emph on 
-signal_t
-\emph default 
- and 
-\emph on 
-port_t
-\emph default 
- based systems, which are described in a further section.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-task_t\SpecialChar ~
-*task_alloc(int\SpecialChar ~
-(*start)(void\SpecialChar ~
-*,\SpecialChar ~
-void\SpecialChar ~
-*), void\SpecialChar ~
-*res,\SpecialChar ~
-void\SpecialChar ~
-*args,\SpecialChar ~
-priority_t\SpecialChar ~
-priorit
-y,\SpecialChar ~
-size_t\SpecialChar ~
-stacksize,\SpecialChar ~
-u_int8_t\SpecialChar ~
-flags)
-\emph default 
- Allocates a task which can then be started or freed back.
-\emph on 
-start
-\emph default 
- specifies the entry point function, 
-\emph on 
-res
-\emph default 
- an optional pointer to a buffer for results which the task may need to
- use or NULL, and 
-\emph on 
-args
-\emph default 
- an optional pointer to a buffer which may be used by the task to obtain
- it's argument, or NULL.
- When 
-\emph on 
-start
-\emph default 
- is called, 
-\emph on 
-res
-\emph default 
- is passed as the first argument and 
-\emph on 
-args
-\emph default 
- as the second one.
-\emph on 
-priority
-\emph default 
- consists of the task initial running priority which may be in the range
- of -128 to 127, 0 being the normal running priority.
-\emph on 
-stacksize
-\emph default 
- specifies the size of the stack in bytes which should be dedicated to the
- task, a common size being 4096 bytes.
-\emph on 
-flags
-\emph default 
- may be 0, or ORed 
-\emph on 
-TS_
-\emph default 
-* flags which are defined in <
-\emph on 
-src/common/kernel/task.h
-\emph default 
->.
- The task is not yet launched by Xisop.
- If the 
-\emph on 
-TS_SHARED
-\emph default 
- flag is supplied, this task will use the 
-\emph on 
-mpool_t
-\emph default 
- of it's parent (the current task which allocates it).
- This means that all memory allocated by one of the tasks sharing a memory
- pool is inherently shared.
- One task ending will not cause the allocated regions to be freed unless
- explicitely freed.
- When all tasks shareing a memory pool exit, all allocated memory by any
- of them is automatically freed back.
- This feature can be used when memory should inherently be shared among
- the tasks, or when memory resources are very scarce.
- However, unlike using Xisop messages which provide synchronization to share
- arbitrary memory regions among tasks, implicit synchronization should be
- used by the tasks when accessing the same shared memory locations which
- they should access concurrently.
- For this, 
-\emph on 
-rwlock_t
-\emph default 
- and 
-\emph on 
-_lock_t
-\emph default 
- based systems can be used, or a custom system based around Xisop signals
- and/or messages.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-task_t\SpecialChar ~
-*task_free(task_t\SpecialChar ~
-*task)
-\emph default 
- Allows to free 
-\emph on 
-task
-\emph default 
- which was previously allocated by 
-\emph on 
-task_alloc()
-\emph default 
-.
- Only tasks which have been allocated but which have not been launched may
- be freed using this function, or it internally does nothing.
- NULL is returned.
- The kernel automatically frees tasks which have been launched when they
- exit.
- When a task is freed, all the resources it allocated using standard Xisop
- functions are automatically freed back to the system as well.
- The exception is when the task was setup with the 
-\emph on 
-TS_SHARED
-\emph default 
- flag, where the memory is only freed when all tasks sharing that memory
- pool ended.
- This does not affect message ports, signals, devices, libraries or handlers,
- however, which are released by each task, always, as they exit.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-task_start(task_t\SpecialChar ~
-*task)
-\emph default 
- Launches 
-\emph on 
-task
-\emph default 
- which should have previously been allocated using 
-\emph on 
-task_alloc()
-\emph default 
-.
- The task is moved to the ready queue and will start executing as soon as
- the current task yields calling 
-\emph on 
-_yield()
-\emph default 
- or is preempted by the scheduler.
- The delay for it to actually execute also depends on the relative priority
- of the tasks on the ready queue and their current credits.
- If synchronization is needed with it's startup, signals or messages can
- be used.
- TRUE is returned on success, or FALSE if the task is invalid, or was already
- launched.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-task_end(task_t\SpecialChar ~
-*task)
-\emph default 
- Immediately forces termination of the specified 
-\emph on 
-task
-\emph default 
-, which may consist of the current task, or of another task.
- The task is cleanly freed as if it exited itself.
- Can also be used on a task which is locked on the waiting queue, perhaps
- waiting for events it will never receive.
- When a task ends and needs to be freed, it is moved in a queue for a dedicated
- task called the reaper, which chores consist of freeing all resources related
- to each task and the tasks themselves on it's own scheduler CPU time slices.
- Other tasks and the kernel are then releaved from that work.
- When a task ends it will soon automatically be freed by Xisop, and the
- resources it allocated are automatically freed as well.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_yield(task_t\SpecialChar ~
-*task)
-\emph default 
- Permits a currently running task to immediately yield control back to the
- scheduler to allow other tasks to have an immediate opportunity to execute,
- rather than leaving the preemtive scheduler interrupt it.
- The task is not moved to the wait queue, and will have an opportunity to
- resume again very soon.
-\emph on 
-task
-\emph default 
- consists of a suggestion to which task to delegate control to, which should
- also currently be in the ready queue.
- When 
-\emph on 
-task
-\emph default 
- is invalid or NULL, the scheduler is left to decide which task to execute
- next.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-task_sleep(task_t\SpecialChar ~
-*task,\SpecialChar ~
-u_int32_t\SpecialChar ~
-flags,\SpecialChar ~
-task_t\SpecialChar ~
-*yield)
-\emph default 
- Allows to immediately switch the specified task (which may also be the
- currently running task) to the waiting queue.
- The task will be unable to execute again until it is specifically moved
- back again on the ready queue by calling 
-\emph on 
-task_wakeup()
-\emph default 
- on it with at least one of the same bits in 
-\emph on 
-flags
-\emph default 
-.
- This can be useful when custom interrupt attached code hooks need to synchroniz
-e tasks and such and that signals and message ports are not desired.
- If the task being put to sleep consists of the current task, 
-\emph on 
-yield
-\emph default 
- can specify another optional ready task to run immediately, if non-NULL.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-task_wakeup(task_t\SpecialChar ~
-*task,\SpecialChar ~
-u_int32_t\SpecialChar ~
-flags)
-\emph default 
- Immediately awakes the specified task if it currently is sleeping in the
- waiting queue.
- This is normally used after a 
-\emph on 
-task_sleep()
-\emph default 
- call was made on the task.
- However, it is possible to use this function to wake a task which is waiting
- for a signal as well if 
-\emph on 
-TSF_SIGNAL
-\emph default 
- flag is specified.
- This is normally used by custom interrupt hooks which need to synchronize
- tasks, when they cannot use signals or message ports.
- They then can share a 
-\emph on 
-fifo_t
-\emph default 
- buffer, or custom 
-\emph on 
-list_t
-\emph default 
- queue, with the wanted tasks and cause them to awake and sleep at will
- for instance.
- The task is only awaken if at least one bit supplied in 
-\emph on 
-flags
-\emph default 
- matches one of the bits of the 
-\emph on 
-flags
-\emph default 
- which were used at 
-\emph on 
-task_sleep()
-\emph default 
-.
- TRUE is returned if the task could be awaken, or FALSE if the flags do
- not permit to awake it or another problem occurs.
-\layout Standard
-
-The current sleeping flags are described as follows (as defined in <
-\emph on 
-src/common/kernel/scheduler.h
-\emph default 
->) :
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-TSF_KERNEL
-\emph default 
- Kernel-reserved, used by the task reaper for instance.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-TSF_SIGNAL
-\emph default 
- Task is waiting for the reception of at least of one of the signal bits
- in 
-\emph on 
-task_t->sigwait
-\emph default 
-.
- Internally used bu the signal subsystem.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-TSF_CUSTOM
-\emph default 
- As the name implies, may be used by user tasks.
-\layout Standard
-
-Here are then described the scheduler control functions:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-priority_t\SpecialChar ~
-task_getpriority(task_t\SpecialChar ~
-*task)
-\emph default 
- Obtains the current running priority level of 
-\emph on 
-task
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-priority_t\SpecialChar ~
-task_setpriority(task_t\SpecialChar ~
-*task,\SpecialChar ~
-priority_t\SpecialChar ~
-p)
-\emph default 
- Permits to change the running priority of 
-\emph on 
-task
-\emph default 
- to 
-\emph on 
-p
-\emph default 
-.
- Returned is the previous priority of 
-\emph on 
-task
-\emph default 
- which could be used to restore it.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-sched_disable(void)
-\emph default 
- Allows to disable the preemptive scheduler, which will only be re-enabled
- when a corresponding number of 
-\emph on 
-sched_enable()
-\emph default 
- have been called, as the scheduler lock consists of a recursive 
-\emph on 
-_rlock_t
-\emph default 
-.
- It is important to not call 
-\emph on 
-yield()
-\emph default 
-, 
-\emph on 
-port_wait(), port_send(), signal_send()
-\emph default 
- or 
-\emph on 
-signal_wait()
-\emph default 
- when the scheduler is disabled, because it would prevent the task from
- ever being awaken again.
- Obviously, this call should be used with care, if any.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-sched_enable(void)
-\emph default 
- Re-enables the scheduler if the same number of instances of this function
- matched with the previous 
-\emph on 
-sched_disable()
-\emph default 
- calls.
-\layout Subsubsection
-
-Locks and synchronization primitives
-\layout Standard
-
-Other synchronization systems such as signals and message ports are later
- described in a next section.
- However, these are also very useful synchronization primitives which Xisop
- provides to both kernelspace and userspace software:
-\layout Paragraph
-
-Exclusive access locks
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_lock_init(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- Initializes an exclusive access a lock.
- This has to be used before using other functions 
-\emph on 
-lock
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_lock_acquire(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- This function is not multitasking-friendly in that the current task loops
- in an endless loop until exclusive obtention of the 
-\emph on 
-_lock_t
-\emph default 
- is acquired.
- Tasks should normally use 
-\emph on 
-lock_acquire()
-\emph default 
- instead.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_lock_release(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- Immediately releases the exclusive 
-\emph on 
-_lock_t
-\emph default 
-\emph on 
-lock
-\emph default 
- to allow another locker to obtain it.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-_lock_try(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- Attempts to exclusively acquire 
-\emph on 
-lock
-\emph default 
-, but returns immediately with FALSE if it cannot.
- TRUE is returned on success.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-_lock_available(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- Returns TRUE if there currently are no locker on 
-\emph on 
-lock
-\emph default 
-, but does not attempt to lock it.
- It is unsafe to attempt to implement 
-\emph on 
-_lock_try()
-\emph default 
- using this function, obviously.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-lock_acquire(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- Similarily to 
-\emph on 
-_lock_acquire()
-\emph default 
-, locks execution of the current task until 
-\emph on 
-lock
-\emph default 
- is exclusively obtained.
- This function is however better according to multitasking as it immediately
- yields CPU time to allow the current locker to free it as soon as possible
- for the current task to own it.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-lock_release(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- Identical to 
-\emph on 
-_lock_release()
-\emph default 
-, made to match 
-\emph on 
-lock_acquire()
-\emph default 
- for consistency.
-\layout Paragraph
-
-Recursive locks
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_rlock_init(_rlock_t\SpecialChar ~
-*lock)
-\emph default 
- Initializes a recursive lock of type 
-\emph on 
-_rlock_t
-\emph default 
-.
- This needs to be performed before calling other recursive lock operations
- on 
-\emph on 
-lock
-\emph default 
-.
- Recursive locks are different from exclusive locks in that there can be
- any number of concurrent lockers at the same time.
- They are usually used for systems which execute at intervals, like the
- Xisop scheduler and interrupt facilities which also make use of this system.
- They can then make sure to be the only locker before performing their critical
- work.
- This way arbitrary tasks may disable the facilities safely by locking the
- lock, and unlocking it when they are done with their critical section.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_rlock_acquire(_rlock_t\SpecialChar ~
-*lock)
-\emph default 
- Locks recusively the 
-\emph on 
-lock
-\emph default 
-\emph on 
-_rlock_t
-\emph default 
-.
- This basically atomically increases the lockers counter of the lock, and
- never fails.
- It always returns immediately.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_rlock_release(_rlock_t\SpecialChar ~
-*lock)
-\emph default 
- Releases the 
-\emph on 
-lock
-\emph default 
-\emph on 
-_rlock_t
-\emph default 
-.
- Note that the same number of release operations must be performed on 
-\emph on 
-lock
-\emph default 
- for it to become available again.
- This only atomically decreases the lockers counter of the lock, and returns
- immediately.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-_rlock_trylock(_rlock_t\SpecialChar ~
-*lock)
-\emph default 
- If the lock is free/available, that is, no current lockers exist on 
-\emph on 
-lock
-\emph default 
-, this function atomically locks it and returns TRUE immediately.
- Otherwise it returns FALSE and returns immediately, in which case the lock
- is left in it's original state before the call.
- This can be very useful for an event-driven system which needs to make
- sure that the lock is free to perform it's tasks, but also needs to prevent
- it's own recursion.
- Obviously, if it returned TRUE, 
-\emph on 
-_rlock_release()
-\emph default 
- is expected to be called when done.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-_rlock_available(_rlock_t\SpecialChar ~
-*lock)
-\emph default 
- Returns FALSE if there are any lockers on 
-\emph on 
-lock
-\emph default 
-, or TRUE if the lock is currently free from any lockers.
- This however only performs the check, and does not change the lock state.
- It is unsafe to use this function along with 
-\emph on 
-_rlock_acquire()
-\emph default 
- to implement a 
-\emph on 
-_rlock_trylock()
-\emph default 
- replacement as it would not be atomic.
-\layout Paragraph
-
-Read/Write locks
-\layout Standard
-
-These locks internally consist of a combination of exclusive and recursive
- locks.
- They are ideal for instance to protect synchronization of resources where
- multiple readers are allowed but that exclusive access is required for
- write operations.
- There currently is provided no way to upgrade a currently held shared access
- lock to an exclusive lock, or to downgrade an exclusively held lock to
- a shared access lock, other than releasing the lock and re-locking it.
- However, if this proves necessary in the future, we shall implement these
- features.
- These locks are especially adequate to protect resources which are frequently
- accessed in read-only mode, but which occasionally need to be updated,
- which obviously requires write/exclusive access, which is the case with
- several Xisop system lists, and these locks are then used by the involved
- kernel functions as well.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-rwlock_init(rwlock_t\SpecialChar ~
-*lock)
-\emph default 
- Initializes 
-\emph on 
-lock
-\emph default 
-, which is necessary before using any other 
-\emph on 
-rwlock_
-\emph default 
-*
-\emph on 
-()
-\emph default 
- function on it.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-rwlock_acquire(rwlock_t\SpecialChar ~
-*lock,\SpecialChar ~
-bool\SpecialChar ~
-exclusive)
-\emph default 
- Locks the current task until the 
-\emph on 
-lock
-\emph default 
-\emph on 
-rwlock_t
-\emph default 
- can be exclusively accessed (for read and/or writing access) if 
-\emph on 
-exclusive
-\emph default 
- is TRUE, or until a shared recursive access is obtained (for read-only
- access) if 
-\emph on 
-exclusive
-\emph default 
- is FALSE.
- Is multitasking-safe.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-rwlock_release(rwlock_t\SpecialChar ~
-*lock)
-\emph default 
- Releases the access on 
-\emph on 
-lock
-\emph default 
- which was obtained using 
-\emph on 
-rwlock_acquire()
-\emph default 
- or 
-\emph on 
-rwlock_try()
-\emph default 
-.
- Whether this access was exclusive or shared is internally remembered.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-rwlock_try(rwlock_t\SpecialChar ~
-*lock,\SpecialChar ~
-bool\SpecialChar ~
-exclusive)
-\emph default 
- Very similar to 
-\emph on 
-rwlock_acquire()
-\emph default 
- but always immediately returns with FALSE if the access cannot be obtained
- immediately.
- TRUE is returned with the lock held on success.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-rwlock_upgrade(rwlock_t\SpecialChar ~
-*lock)
-\emph default 
- Permits to upgrade an already obtained shared lock to an exclusive lock.
- The current task may sleep as required until all shared lockers free their
- lock.
- The caller 
-\emph on 
-MUST
-\emph default 
- already be holding the lock in shared mode.
- This function is most useful for operations such as check-and-modify, when
- read-only access is generally required to a resource, but that under certain
- conditions write access is needed to modify the resource after the check.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-rwlock_downgrade(rwlock_t\SpecialChar ~
-*lock)
-\emph default 
- Conversely to 
-\emph on 
-rwlock_upgrade()
-\emph default 
-, allows to downgrade an already obtained exclusive lock to a shared lock.
- The caller 
-\emph on 
-MUST
-\emph default 
- already be holding this lock in exclusive mode.
- The usefulness of this function is questionable.
- Although provided, the kernel does not use it.
-\layout Paragraph
-
-System lists access
-\layout Standard
-
-Several system lists require internal 
-\emph on 
-rwlock_t
-\emph default 
- for synchronization against corruption.
- In <
-\emph on 
-common/kernel/main.h
-\emph default 
-> are defined several macros which can be used to access those securely
- by kernel functions.
- The 
-\emph on 
-enum systables
-\emph default 
- specifies various system lists which can be accessed using these methods,
- called 
-\emph on 
-SYSTABLE_
-\emph default 
-*.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-SYSTABLE_RLOCK(enum\SpecialChar ~
-systables\SpecialChar ~
-table)
-\emph default 
- Locks the 
-\emph on 
-rwlock_t
-\emph default 
- of the specified 
-\emph on 
-table
-\emph default 
-, in shared mode (read-only access).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-SYSTABLE_WLOCK(enum\SpecialChar ~
-systables\SpecialChar ~
-table)
-\emph default 
- Locks the 
-\emph on 
-rwlock_t
-\emph default 
- of the specified 
-\emph on 
-table
-\emph default 
-, in exclusive mode (read/write access).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-SYSTABLE_UNLOCK(enum\SpecialChar ~
-systables\SpecialChar ~
-table)
-\emph default 
- Unlocks the 
-\emph on 
-rwlock_t
-\emph default 
- of the specified 
-\emph on 
-table
-\emph default 
-, which should have previously been locked using 
-\emph on 
-SYSTABLE_RLOCK()
-\emph default 
- or 
-\emph on 
-SYSTABLE_WLOCK()
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-SYSTABLE_UPGRADE(enum\SpecialChar ~
-systables\SpecialChar ~
-table)
-\emph default 
- Allows a caller which 
-\emph on 
-MUST
-\emph default 
- hold a shared read-only access lock (after using 
-\emph on 
-SYSTABLE_RLOCK()
-\emph default 
-) to upgrade the lock to exclusive mode.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-hashtable_t\SpecialChar ~
-*SYSTABLE(enum\SpecialChar ~
-systables\SpecialChar ~
-table)
-\emph default 
- Returns the 
-\emph on 
-hashtable_t
-\emph default 
- pointer associated with the system list 
-\emph on 
-table
-\emph default 
-.
- Obviously, this should only be used when the lock is held, and should only
- be used for the access corresponding to the currently obtained lock type.
-\layout Standard
-
-The following two functions, as opposed to macros, are implemented as C
- functions and perform boundary checking on the arguments, as they are provided
- for user tasks rather than for the kernel, for which the previous macros
- were designed:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-hashtable_t\SpecialChar ~
-*systable_lock(u_int32_t\SpecialChar ~
-systable,\SpecialChar ~
-bool\SpecialChar ~
-exclusive)
-\emph default 
- Attempts to lock access to the system list 
-\emph on 
-systable
-\emph default 
-, in exclusive or shared mode.
- A pointer to the 
-\emph on 
-hashtable_t
-\emph default 
- is returned on success, or NULL otherwise.
- As usual, shared locks should be obtained when read-only access is performed
- on a list, but an exclusive lock is required if there is any need to modify
- a system list.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-systable_unlock(u_int32_t\SpecialChar ~
-systable)
-\emph default 
- Unlocks a previously held lock for 
-\emph on 
-systable
-\emph default 
-, which should have previously been obtained using 
-\emph on 
-systable_lock()
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-systable_upgrade(u_int32_t\SpecialChar ~
-systable)
-\emph default 
- Upgrades a previously held lock for systable in shared mode to exclusive
- mode.
- The lock 
-\emph on 
-MUST
-\emph default 
- previously be obtained in shared mode.
-\layout Subsubsection
-
-Signals
-\layout Standard
-
-Very few signals are reserved by the system, SIGTERM and SIGPOLL, respectively.
- As Xisop currently supports 32 different signals per task, this results
- in 30 user signals the applications programmer may play with.
- Signals are internally implemented as bits, and are not reliably queued,
- which means that although a task will always know that a particular signal
- was received, it cannot know if it occured more than once before it had
- the chance to process it.
- It ressembles alot to a hardware bus line, which can be activated by the
- other end, although our capacity to monitor a single signal state is dependent
- on the rate at which we run.
-\layout Standard
-
-Note that sending a SIGTERM signal to a task does not force it to exit.
- It merely consists of a request to exit to the task, and the task may ignore
- it or respect it.
-\layout Standard
-
-
-\emph on 
-XXX 32 is no longer a fixed value now that signum_t and sigmask_t are abstracted
- and could be set by the port-specific code.
-\layout Standard
-
-Message ports are used when the need for reliable event queuing is met.
- The signals merely allow a task to sleep and be awaken on specified events,
- like a message arriving on a port, which internally uses a signal bit.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-signum_t\SpecialChar ~
-signal_alloc(void)
-\emph default 
- Attempts to allocate an available signal bit from the current task.
- Returns the signal number allocated, or -1 if no more signals available.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-signal_free(sigmask_t\SpecialChar ~
-sigmask)
-\emph default 
- Frees all specified signals in 
-\emph on 
-sigmask
-\emph default 
-, which should previously have been obtained using 
-\emph on 
-signal_alloc()
-\emph default 
-.
- If reserved signals are part of the supplied 
-\emph on 
-sigmask
-\emph default 
-, those are ignored.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-sigmask_t\SpecialChar ~
-signal_wait(sigmask_t\SpecialChar ~
-sigmask,\SpecialChar ~
-task_t\SpecialChar ~
-*task)
-\emph default 
- Suspends the current task until at least one of the supplied signals in
-\emph on 
-sigmask
-\emph default 
-, or a system reserved signal occurs.
- Returned is the mask of signals we received which caused an awakening.
- Multitasking-friendly applications usually spend most of their time suspended
- by this call, and are awakening to perform their operations asynchroneously,
- and go back to sleep as soon as possible, to allow other tasks to also
- respond and execute efficienty.
- However, because of the nature of the preemptive scheduler, a task which
- remains in running state will not prevent others from executing.
-\emph on 
-task
-\emph default 
-, which may be NULL, optionally specifies which task should be favored as
- a suggestion to the scheduler, which allows to implement cooperative tasks
- more efficiently.
- The current task is guaranteed to awake at the occurance of the specified
- signals, but will not be able to determine how many occurances of each
- signal occurred as no queueing is performed.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-signal_send(task_t\SpecialChar ~
-*task,\SpecialChar ~
-sigmask_t\SpecialChar ~
-sigmask)
-\emph default 
- Atomically sends the supplied signals in 
-\emph on 
-sigmask
-\emph default 
- to the specified 
-\emph on 
-task
-\emph default 
-.
- The task, if suspended waiting for signals, is awaken if a signal it waits
- for is included in 
-\emph on 
-sigmask
-\emph default 
-, and will have a chance to run.
- The delay elapsing between 
-\emph on 
-signal_send()
-\emph default 
- and the task being able to process the signal depends on three factors:
-\begin_deeper 
-\layout Itemize
-
-The speed at which the current task returns to sleep (using 
-\emph on 
-yield()
-\emph default 
-, 
-\emph on 
-port_wait()
-\emph default 
- or 
-\emph on 
-signal_wait()
-\emph default 
-).
-\layout Itemize
-
-If it does not return to sleep, the current task will continue running until
- it is preempted by the scheduler, which is dependent on the scheduler timer
- interrupt frequency.
-\layout Itemize
-
-The priority of the tasks in the ready queue, that is, which are currently
- awake.
- This factor takes place after the other end was awaken, and before it gets
- an opportunity to actually execute.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-sigmask_t\SpecialChar ~
-SIGMASK(signum_t\SpecialChar ~
-signum)
-\emph default 
- Consists of a useful macro to convert a signal number (
-\emph on 
-signum_t
-\emph default 
-) to a signal mask (
-\emph on 
-sigmask_t
-\emph default 
-).
- Those may then be ORed together (using C '|' bitwise operator character)
- to represent multiple signals.
-\layout Subsubsection
-
-Message ports
-\layout Standard
-
-In the UNIX world, this is called Inter Process Communication (IPC).
- In the case of Xisop, we communicate between light-weight tasks, rather
- than between full fledged processes, using signals, datagram messages and
- connectionless, unidirectional ports.
- The Xisop port functions internally operate using signal primitives and
- message queues (in FIFO order).
- These are safe to call from userspace as well as kernelspace tasks.
- However, it is not safe to transfer messages among ports in an interrupt
- handler context without using 
-\emph on 
-_splhigh()
-\emph default 
- for synchronization.
-\emph on 
-XXX
-\layout Standard
-
-A Xisop message consists of an arbitrary sized object prefixed with a 
-\emph on 
-message_t
-\emph default 
- structure, which is internally used for message queueing and replying informati
-on.
- Because the message is internally 
-\begin_inset Quotes eld
-\end_inset 
-
-moved
-\begin_inset Quotes erd
-\end_inset 
-
- by only swapping pointers efficiently, memory copy operations are minimized.
- However, this also means that the original creator of the message, as well
- as the other end to which the message is passed, are responsible to synchronize
- operations properly among eachother on the message memory area (more informatio
-n on this below).
- The 
-\emph on 
-message_t
-\emph default 
- header starts with a 
-\emph on 
-pnode_t
-\emph default 
- internally, which means that the user can use 
-\emph on 
-pool_t
-\emph default 
- primitives to efficiently and arbitrarily create and destroy messages.
- It also means that at their discretion the ends are able to internally
- queue the message in custom 
-\emph on 
-list_t
-\emph default 
- lists when necessary (after 
-\emph on 
-port_get()
-\emph default 
-, and taking care to unlink it before 
-\emph on 
-port_send()
-\emph default 
-/
-\emph on 
-port_reply()
-\emph default 
-, obviously).
-\layout Standard
-
-Some care was made when implementing Xisop message ports to take in consideratio
-n tasks and or ports which may be destroyed before a message is replied
- back by the other end, or for cases where a public port address, after
- being obtained once, becomes invalid as the public service dies.
- Instead of implementing a higher overhead or less versatile unique port
- ID allocation, validation and lookup system, or using expensive string
- operations with a 
-\emph on 
-hashtable_t
-\emph default 
- using 
-\emph on 
-hashtable_lookup()
-\emph default 
- for every message send, the following techniques were implemented:
-\layout Itemize
-
-A special magic cookie is set on a valid, existing port.
- This means that when attempting to perform any operation on a 
-\emph on 
-port_t
-\emph default 
- pointer which does not resolve to an actual, currently valid port, operation
- is refused to take place.
- When a message port is destroyed, that magic number is reset to zero, which
- renders it unusable.
-\layout Itemize
-
-Because an efficient 
-\emph on 
-pool_t
-\emph default 
- is used to allocate and free back 
-\emph on 
-port_t
-\emph default 
- objects, it would be possible for an intended reply port to be destroyed,
- and for another port, belonging to any task, to be created at the same
- address.
- To solve this issue, each port also comports an internal unique ID.
- When a message is sent to a port, from which a reply is expected, the 
-\emph on 
-message_t
-\emph default 
- is made to remember both the reply 
-\emph on 
-port_t
-\emph default 
- address and unique ID.
- When attempting to reply, the 
-\emph on 
-port_t
-\emph default 
- validity is performed as usual via the magic number, and the unique ID
- is then evaluated for a match.
- This way, a reply message will never be queued back on an unexpected port,
- or to a nonexisting one which may just have died.
-\layout Itemize
-
-The unique ID supplied to a port only consists of an unsigned 32-bit integer,
- which is obtained from a global shared counter, which is incremented and
- used whenever required.
- This means that the odds of another 
-\emph on 
-port_t
-\emph default 
- using the same address and ID within the delay of a send/reply are probably
- always none.
-\layout Itemize
-
-Using this method prevented restrictions on the maximum number of ports
- and tasks which can exist in Xisop.
- The overhead is also smaller than having to run through an array looking
- for an empty slot, and having to re-allocate the memory area to dynamically
- grow or shrink it, because without MMU support alot of memory copying would
- be required for those operations.
- Using a 
-\emph on 
-pool_t
-\emph default 
- then is ideal for speed.
- Using a relatively fast lookup hash table would require a lookup to be
- performed before every message send, which was considered suboptimal when
- designing Xisop.
- Although 
-\emph on 
-port_find()
-\emph default 
- uses this, it would have been absurd to need to perform this lookup before
- sending any message.
- Especially considering that locking must be used when accessing the system
- hash table for synchronization.
-\layout Standard
-
-Usually, the tasks should be written to be reliable and to synchronize well
- within eachother.
- However, with these precautions, supported by well written applications,
- the 
-\emph on 
-port_t
-\emph default 
- system is always very reliable and predictable.
- Here are described the functions:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-port_t\SpecialChar ~
-*port_create(const\SpecialChar ~
-char\SpecialChar ~
-*name)
-\emph default 
- Allows to create a message port on the current task.
- This internally also needs to allocate a signal bit using 
-\emph on 
-signal_alloc()
-\emph default 
-, which is associated to the 
-\emph on 
-port_t
-\emph default 
- for the 
-\emph on 
-port_wait()
-\emph default 
- internals.
- NULL is returned on failure, or a pointer to the new 
-\emph on 
-port_t
-\emph default 
- on success.
-\emph on 
-name
-\emph default 
- is optional and should be NULL if the port does not need to be advertized
- to the whole system.
- If other tasks need to find our port by name, then 
-\emph on 
-name
-\emph default 
- will be usable with 
-\emph on 
-port_find()
-\emph default 
- to locate it, and listing the system public ports would advertize it as
- well.
- Ports are generally private, except for special public services.
- The length of 
-\emph on 
-name
-\emph default 
- will be truncated to 32 characters if it is longer.
- If a public port is created, but that another public port bears the same
- name alerady, the operation fails.
- The port name is case-sensitive.
- If the task exists without closing it's ports, they are automatically destroyed
- by the kernel.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-port_t\SpecialChar ~
-*port_destroy(port_t\SpecialChar ~
-*port)
-\emph default 
- Destroys a message port of the current process, which was created using
-\emph on 
-port_create()
-\emph default 
-.
- The internally allocated signal bit and memory are released back to the
- system.
- If any queued messages exist, the queue is lost, but the 
-\emph on 
-message_t
-\emph default 
- objects are untouched, as they remain the responsibility of the application
- who created them.
- NULL is returned.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-port_t\SpecialChar ~
-*port_find(const\SpecialChar ~
-char\SpecialChar ~
-*name)
-\emph default 
- Allows to locate a public message port by name.
- If the port can be found, it's address is returned.
- NULL is returned otherwise.
- Because this needs to lookup through a system's public ports hash table
- it needs to lock it internally using a 
-\emph on 
-rwlock_t
-\emph default 
- in shared access mode.
- The port name is case-sensitive.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-port_send(port_t\SpecialChar ~
-*port,\SpecialChar ~
-port_t\SpecialChar ~
-*replyport,\SpecialChar ~
-message_t\SpecialChar ~
-*message)
-\emph default 
- Queues the supplied 
-\emph on 
-message_t
-\emph default 
- to the specified 
-\emph on 
-port_t
-\emph default 
- in FIFO order, and internally 
-\emph on 
-send_signal()
-\emph default 
- the associated process with the internal port signal.
- This means that the other process could be sleeping using 
-\emph on 
-signal_wait()
-\emph default 
- or 
-\emph on 
-port_wait()
-\emph default 
- and will be awakened so that it may process the message.
- The supplied message then becomes owned by the other end, and should be
- left alone by the current task until a reply be obtained from the other
- side on the 
-\emph on 
-message_t
-\emph default 
-'s 
-\emph on 
-replyport
-\emph default 
-.
- This 
-\emph on 
-port_send()
-\emph default 
- and 
-\emph on 
-port_reply()
-\emph default 
- mechanism serves for synchronization.
- This means that normally, 
-\emph on 
-replyport
-\emph default 
- is supplied the address of a local 
-\emph on 
-port_t
-\emph default 
- used to receive results from the task we send messages to via it's own
-\emph on 
-port_t
-\emph default 
-.
- TRUE is returned on success, or FALSE if the message could not be delivered
- (in which case the supplied 
-\emph on 
-port_t
-\emph default 
- address is probably invalid and a 
-\emph on 
-port_find()
-\emph default 
- operation can be used again to attempt to locate the port, if it consists
- of a public port which should exist).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-message_t\SpecialChar ~
-*port_get(port_t\SpecialChar ~
-*port)
-\emph default 
- If at least one message is available in the specified 
-\emph on 
-port_t
-\emph default 
-, the first one is unqueued from it in FIFO order and the address to it
- is returned.
- Otherwise, NULL is returned.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-port_reply(message_t\SpecialChar ~
-*msg)
-\emph default 
- Sends back the supplied 
-\emph on 
-message_t
-\emph default 
- to the reply 
-\emph on 
-port_t
-\emph default 
- of the task that previously sent it to us.
- This port corresponds to the 
-\emph on 
-replyport
-\emph default 
- argument that was used at 
-\emph on 
-port_send()
-\emph default 
-.
- Normally, the other end waits until we are done with the message, and we
- use this function to notify that it can safely continue to do whatever
- it wants with the 
-\emph on 
-message_t
-\emph default 
- data.
- TRUE is returned on success, or FALSE if no 
-\emph on 
-replyport
-\emph default 
- was set for the 
-\emph on 
-message_t
-\emph default 
-, or that the reply port is no longer valid.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-port_t\SpecialChar ~
-*port_wait(port_t\SpecialChar ~
-**ports,\SpecialChar ~
-u_int32_t\SpecialChar ~
-num,\SpecialChar ~
-task_t\SpecialChar ~
-*task)
-\emph default 
- Suspends the current task until a message is received through one of the
- supplied port(s) specified in the array of 
-\emph on 
-port_t
-\emph default 
- pointers 
-\emph on 
-ports
-\emph default 
-.
-\emph on 
-num
-\emph default 
- specifies the number of 
-\emph on 
-port_t
-\emph default 
- pointers supplied in the ports array.
-\emph on 
-task
-\emph default 
- specifies a suggestion preference of which task to switch to, or NULL to
- let the scheduler choose.
- Returned is the pointer to the 
-\emph on 
-port_t
-\emph default 
- which received the message, or NULL if a reserved signal was the awakening
- cause.
- If one of the ports already has queued messages the task will not be set
- to sleep and the aforementionned port will be returned immediately.
- If it is necessary to monitor other signals as well as port message arrivals,
- it is advised to manually assemble the 
-\emph on 
-sigmask_t
-\emph default 
- from all monitored signals, including the ones associated to the monitored
- ports, and to use 
-\emph on 
-signal_wait()
-\emph default 
- instead.
- Evaluating the resulting 
-\emph on 
-sigmask_t
-\emph default 
- will permit to know which ports received messages, if any.
- Use of the 
-\emph on 
-PORT_SIGMASK()
-\emph default 
- macro will then be useful.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-port_flush(port_t\SpecialChar ~
-*port)
-\emph default 
- Unqueues all pending messages in the supplied 
-\emph on 
-port_t
-\emph default 
-, if any.
- This can be useful to discard unused 
-\emph on 
-port_reply()
-\emph default 
- results which are obtained where no result codes are needed, rather than
- using a 
-\emph on 
-while()
-\emph default 
- loop of 
-\emph on 
-port_get()
-\emph default 
- statements.
- Also useful before destroying ports when desired.
- Returns TRUE on success, or FALSE if the port is invalid.
- Should obviously not be used on other tasks' ports, only ours.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-sigmask_t\SpecialChar ~
-PORT_SIGMASK(port_t\SpecialChar ~
-*port)
-\emph default 
- Is useful when it is necessary to know which signal bit is associated with
- a particular port.
- The returned 
-\emph on 
-sigmask_t
-\emph default 
- can be ORed with the other masks to provide to 
-\emph on 
-signal_wait()
-\emph default 
-.
- This way, it is possible for a task to monitor the state of other signals
- while at the same time monitoring message ports for events.
- This macro, just like 
-\emph on 
-SIGMASK()
-\emph default 
-, should be used instead of expressions such as 
-\emph on 
-(1L << n)
-\emph default 
- both for code obviousness and backwards compatibility, because the number
- of available signals could eventually grow.
-\layout Subsubsection
-
-The special SIGPOLL signal and the poll port
-\layout Standard
-
-
-\emph on 
-XXX needs to be rethinked and re-written :)
-\layout Standard
-
-As there only are 30 user signals, and that a message port is usually associated
- with a signal, it may be useful to assign more than one message port to
- a single signal, or process more than one event using a single signal and
- message port.
-\layout Standard
-
-The SIGPOLL signal is reserved for just that, and each task always has a
- message port associated with this signal.
- Through this port can be sent various type of messages for more than one
- event the task may want to be awakened for.
- This provides message multiplexing, while the method for multiple message
- ports using the same signal would provide port multiplexing.
- The reason why message multiplexing was chosen as a standard in Xisop was
- because it requires less resources.
- The more ports there are on the system, the larger the system ports pool
- grows and it will never shrink for considerations described in the previous
- subsection.
-\emph on 
-XXX
-\layout Standard
-
-This special system-reserved port can be used to transfer reliable signals,
- possibly emulating POSIX semantics, or to transfer many other types of
- events a task may all be waiting for.
- It also is useful to have a high number of concurrently opened high-level
- files, and implement filedescriptors.
- A special set of functions is provided by Xisop machine-independent layer
- to transfer messages through this port, and to evaluate the type of event
- that originated the message, along with message size.
- Because unlike for standard message ports where messages of a fixed size
- are usually transfered, the message size changes here, depending on the
- event type and message.
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsection
-
-Xisop memory management system
-\layout Standard
-
-Xisop provides three types of memory management primitives for the kernel.
- These are provided by the Xisop machine-independent layer.
- It also provides distinction between the various types of memory, when
- an architecture has more than one (i.e.
- Amiga CHIP and FAST RAM, peripheral memory, etc).
- Special care was used to prevent the memory management system from having
- to disable interrupts (which may be very useful when the 
-\emph on 
-_FACILITY_SCHEDTIMER
-\emph default 
- consists of the only timing source for an architecture and needs to be
- as reliable as possible).
- A 
-\emph on 
-_lock_t
-\emph default 
- is internally used by the system page primitives to sychronize access to
- the system page pools.
- This also avoids having to export them as system calls via traps.
-\layout Subsubsection
-
-Page primitives
-\layout Standard
-
-The first level system consists of page allocation and freeing.
- The page size is dependent on architecture when MMU is concerned, however
- within Xisop which provides it's own memory management, a page is typically
- 4096 bytes.
- Primitives are provided to allocate a single page, or number of physically
- contiguous pages, and to free back one page, or a number of contiguous
- pages.
- At system initialization, the page pools are initiated to provide access
- to the physical memory areas, and are classified by memory type.
- There are a few functions also defined by Xisop which allow to add physical
- memory areas to the page pools, and specify their type, so that the architectur
-e-dependent initialization code be simpler, and also that at runtime it
- be possible to attach new RAM which was mapped from external devices, possibly
- hot-pluggable ones such as PCMCIA memory cards, etc.
- Here are described the dynamic memory linking functions.
- Note that these functions internally use a 
-\emph on 
-_lock_t
-\emph default 
- which is acquired to access the system pages pools.
- This means that they are generally safe to call anytime, but from interrupt
- handler context.
-\emph on 
-XXX
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-mchunk_t\SpecialChar ~
-*mchunk_init(void\SpecialChar ~
-*mem,\SpecialChar ~
-size_t\SpecialChar ~
-size)
-\emph default 
- Internally prepares the supplied memory block to pages which can later
- be linked into the system.
- The internal control structures are setup in hidden data which will not
- be added into the public pages.
- This is dependent on 
-\emph on 
-_PAGE_SIZE
-\emph default 
-, which should be defined by the port-specific <
-\emph on 
-port/support.h
-\emph default 
-> headerfile.
- NULL is returned if the supplied memory area was too small to be split
- into pages and to store the necessary control data.
- Otherwise, a pointer to the 
-\emph on 
-mchunk_t
-\emph default 
- is provided.
- After using this call, the memory area should never be manipulated anymore,
- other than using other Xisop standard calls, unless it is known that the
- area is not linked into the system pages.
- The supplied memory is expected to be physical contiguous memory.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-mchunk_attach(int\SpecialChar ~
-memtype,\SpecialChar ~
-mchunk_t\SpecialChar ~
-*mchunk)
-\emph default 
- Allows to link an 
-\emph on 
-mchunk_t
-\emph default 
- which was previously prepared using 
-\emph on 
-mchunk_init()
-\emph default 
-, to the system 
-\emph on 
-ppool_t
-\emph default 
- associated with the specified memory type.
- After this is performed, it is possible to allocate memory pages from this
- memory chunk until it be unlinked using 
-\emph on 
-mchunk_detach()
-\emph default 
-.
- This depends on 
-\emph on 
-_MEM_MAX
-\emph default 
-, which is defined by the port specific <
-\emph on 
-port/support.h
-\emph default 
-> headerfile.
- TRUE is normally returned, unless the chunk is seen to already have been
- attached, or that the supplied memory type is invalid, in which case FALSE
- is returned.
- It is possible to setup and append as many 
-\emph on 
-mchunk_t
-\emph default 
- as wanted.
- For instance, the port-specific code which sets up the kernel pages for
- available memory may need to call 
-\emph on 
-mchunk_init()
-\emph default 
- and 
-\emph on 
-mchunk_attach()
-\emph default 
- multiple times, one for each contiguous memory block.
- It is safe to call this function to attach new memory at system runtime,
- anytime.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-mchunk_detach(int\SpecialChar ~
-memtype,\SpecialChar ~
-mchunk_t\SpecialChar ~
-*mchunk)
-\emph default 
- Permits to safely detach from the system an 
-\emph on 
-mchunk_t
-\emph default 
- which previously was attached using 
-\emph on 
-mchunk_attach()
-\emph default 
-.
- TRUE is returned on success, or FALSE if the memory type is invalid, if
- the supplied 
-\emph on 
-mchunk_t
-\emph default 
- was not currently attached, or if any memory from that 
-\emph on 
-mchunk_t
-\emph default 
- is still currently allocated, in which case the chunk is not unliked.
-\layout Standard
-
-The first level of allocation primitives allow to allocate and free one
- or multiple contiguous pages of physical memory to and from the system
- pools (
-\emph on 
-ppool_t
-\emph default 
- of each memory type).
- Internally, the list of linked 
-\emph on 
-mchunk_t
-\emph default 
- for a memory type is ran through.
- These functions also acquire the system pools safety lock while working
- on the system memory pools:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-page_t\SpecialChar ~
-*pages_alloc(int\SpecialChar ~
-memtype,\SpecialChar ~
-u_int32_t\SpecialChar ~
-many,\SpecialChar ~
-bool\SpecialChar ~
-zero)
-\emph default 
- Allocates 
-\emph on 
-many
-\emph default 
- contiguous memory pages of 
-\emph on 
-_PAGE_SIZE
-\emph default 
- bytes, of the supplied 
-\emph on 
-memtype
-\emph default 
-, which can be 
-\emph on 
-_MEM_ANY
-\emph default 
- in which case all memory types are tried sequencially, favoring the first
- memory type to the last.
- A 
-\emph on 
-page_t
-\emph default 
- pointer is returned which can be used to access the memory area via 
-\emph on 
-page_t->address
-\emph default 
-, or to free back the memory using 
-\emph on 
-pages_free()
-\emph default 
-.
- NULL is returned if not enough memory can be found to satisfy the request.
- If 
-\emph on 
-zero
-\emph default 
- is TRUE and pages could be allocated, the memory area is zeroed using 
-\emph on 
-pageclr()
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-pages_free(page_t\SpecialChar ~
-*pages)
-\emph default 
- Releases to the system one or more contiguous memory pages which previously
- were allocated using 
-\emph on 
-pages_alloc()
-\emph default 
-.
- TRUE is returned on success, or FALSE if the supplied pointer was NULL,
- or if the 
-\emph on 
-page_t
-\emph default 
- was already freed back.
-\layout Subsubsection
-
-Simple object pool primitives
-\layout Standard
-
-The second level consists of a pool of fixed sized entities, the 
-\emph on 
-pool_t
-\emph default 
-.
- A pool can be pre-allocated once, with a fixed maximum number of elements,
- setup to grow automatically when new elements are needed, internally allocating
- and preparing new pages as required, and can optionally also shrink smaller
- automatically, releasing back to the system the unused pages.
- When a pool is about to shrink, it evaluates statistics about the number
- of pages the pool normally holds on average, so that primitives to free
- the page are not called too often unnecessarily.
- Such pages are buffered by the pool for future use, if they are expected
- to be reclaimed back soon.
- Using these functions is more efficient in speed and memory than using
- page allocation primitives, calls to which it attempts to minimize, while
- filling each page of memory with the most objects possible.
-\layout Standard
-
-A C structure should be defined for the type of object which is to be allocated,
- and the first element of that structure should consist of a 
-\emph on 
-pnode_t
-\emph default 
- element.
- These functions, unlike page allocation ones, do not synchronize if multiple
- tasks or interrupt handlers share a 
-\emph on 
-pool_t
-\emph default 
-.
- The caller should therefore provide synchronization whenever necessary.
- However, if the 
-\emph on 
-pool_t
-\emph default 
- allocates or frees system pages, the 
-\emph on 
-pages_alloc()
-\emph default 
- and 
-\emph on 
-pages_free()
-\emph default 
- functions are used which internally use synchronization to ensure that
- the system pools do not corrupt.
- These functions are mostly for kernel use.
- If used from userspace, these pools will not be automatically freed back
- to the system unless the tasks specifically destroys them before exiting.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-pool_init(pool_t\SpecialChar ~
-*p, u_int32_t\SpecialChar ~
-stepp, u_int32_t\SpecialChar ~
-minp, u_int32_t\SpecialChar ~
-maxp, size_t\SpecialChar ~
-node
-size, int\SpecialChar ~
-memtype)
-\emph default 
- Initializes the supplied 
-\emph on 
-pool_t
-\emph default 
- object 
-\emph on 
-p
-\emph default 
- to be used to allocate objects of 
-\emph on 
-nodesize
-\emph default 
- length (size which should include the 
-\emph on 
-pnode_t
-\emph default 
- element).
- This size should be equal or smaller than 
-\emph on 
-_PAGE_SIZE
-\emph default 
- * 
-\emph on 
-stepp
-\emph default 
- / 2.
-\emph on 
-stepp
-\emph default 
- specifies how many contiguous pages should be allocated and freed at once
- using 
-\emph on 
-pages_
-\emph default 
-*
-\emph on 
-()
-\emph default 
- primitives, when required.
- If 
-\emph on 
-stepp
-\emph default 
- appears too small to fit a useful number of nodes in a 
-\emph on 
-page_t
-\emph default 
-, it will be automatically grown until it reaches a maximum of 8, after
- which FALSE will be returned for failure (although there is no such limit
- for the 
-\emph on 
-stepp
-\emph default 
- argument itself when manually set high enough).
- Each 
-\emph on 
-page_t
-\emph default 
- is then internally split into objects.
-\emph on 
-minp
-\emph default 
- tells the minimum number of 
-\emph on 
-page_t
-\emph default 
- which should always remain into the 
-\emph on 
-pool_t
-\emph default 
-, or 0 if it is allowed to shrink totally when it needs no memory.
- The pool will initially allocate those at initialization, and it will never
- shrink smaller during it's lifetime, if non-zero.
-\emph on 
-maxp
-\emph default 
- similarily specifies the maximum number of 
-\emph on 
-page_t
-\emph default 
- which the 
-\emph on 
-pool_t
-\emph default 
- should eventually grow to, or 0 for no limit.
- For instance, using 
-\emph on 
-minp
-\emph default 
- and 
-\emph on 
-maxp
-\emph default 
- of 0 allows the pool_t to dynamically grow and shrink as necessary and
- it could eventually use all available RAM.
- Using a 
-\emph on 
-minp
-\emph default 
- and 
-\emph on 
-maxp
-\emph default 
- of 2 ensures that at least two 
-\emph on 
-page_t
-\emph default 
- be initially allocated, which will never be freed back unless the 
-\emph on 
-pool_t
-\emph default 
- is destroyed, and also tells that the pool should never allocate more pages.
- This can be useful in interrupt context or some situations where we do
- not want the system pool pages to be accessed.
- A fixed number of maximum object nodes will be available to allocate and
- free efficiently then.
-\emph on 
-memtype
-\emph default 
- specifies the memory type which this pool will use to allocate the pages.
- It is invalid to specify 
-\emph on 
-_MEM_ANY
-\emph default 
- here.
- TRUE is returned on success, or FALSE on failure (invalid memory type or
- not enough available memory).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-pool_destroy(pool_t\SpecialChar ~
-*pool)
-\emph default 
- Frees all memory currently being used by the specified 
-\emph on 
-pool_t
-\emph default 
- and destroys the pool object, which can no longer be used by pool object
- allocation primitives unless it is re-initialized.
- Any currently allocated objects from the 
-\emph on 
-pool_t
-\emph default 
- become invalid immediately and should therefore not be accessed anymore,
- they get freed as well.
- TRUE is returned on success, or FALSE if the supplied 
-\emph on 
-pool_t
-\emph default 
- was not previously initialized successfully.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-pnode_t\SpecialChar ~
-*pool_alloc(pool_t\SpecialChar ~
-*pool,\SpecialChar ~
-bool\SpecialChar ~
-zero)
-\emph default 
- Attempts to allocate a single object from the specified 
-\emph on 
-pool_t
-\emph default 
-.
- The object size depends on the 
-\emph on 
-nodesize
-\emph default 
- parameter which was supplied at 
-\emph on 
-pool_init()
-\emph default 
-.
- A pointer to the object is returned on success, or NULL if not enough memory
- is available, either for the 
-\emph on 
-pool_t
-\emph default 
-, if 
-\emph on 
-maxp
-\emph default 
- was non-zero, or system memory.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-pnode_t\SpecialChar ~
-*pool_free(pnode_t\SpecialChar ~
-*node)
-\emph default 
- Releases the specified object 
-\emph on 
-node
-\emph default 
- which was previously allocated using 
-\emph on 
-pool_alloc()
-\emph default 
-, back to the 
-\emph on 
-pool_t
-\emph default 
- it belongs to.
- NULL is returned.
-\layout Subsubsection
-
-General purpose memory pools
-\layout Standard
-
-The third level memory management system, working with 
-\emph on 
-mpool_t
-\emph default 
-, consists of a number of 
-\emph on 
-pool_t
-\emph default 
-, adapted to serve most byte requirement requests, through more standard
- malloc() and free() like functions.
- For a system with a 
-\emph on 
-_PAGE_SIZE
-\emph default 
- of 4096, 
-\emph on 
-_MPOOLSTEP
-\emph default 
- of 1 and 
-\emph on 
-_MPOOLS
-\emph default 
- of 7 and 
-\emph on 
-_MPOOLSTART
-\emph default 
- of 16, there are 7 
-\emph on 
-pool_t
-\emph default 
-, deserved to serve element sized as closely possible to the requested number
- of bytes (smallest nodesize 16 + sizeof(mnode_t)), and a 
-\emph on 
-list_t
-\emph default 
- designed to hold 
-\emph on 
-page_t
-\emph default 
- pointers to satisfy larger requests, which get rounded on page boundaries.
- An 
-\emph on 
-mpool_t
-\emph default 
- is capable of serving requests for various memory types, including 
-\emph on 
-_MEM_ANY
-\emph default 
-, where the first memory types are privileged over the last ones.
- Like their 
-\emph on 
-pool_t
-\emph default 
- counterparts, these functions do not perform any special synchronization
- which may be necessary if an 
-\emph on 
-mpool_t
-\emph default 
- was shared among several tasks.
- Here are the functions related to the 
-\emph on 
-mpool_t
-\emph default 
-:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-mpool_init(mpool_t\SpecialChar ~
-*mpool)
-\emph default 
- Initializes an 
-\emph on 
-mpool_t
-\emph default 
- to accept allocation requests.
- TRUE is returned on success, or FALSE if there is a problem initializing
- the 
-\emph on 
-pool_t
-\emph default 
- elements, or if the supplied 
-\emph on 
-mpool
-\emph default 
- pointer is NULL.
- This function is dependent on the port-specific 
-\emph on 
-_MPOOLS
-\emph default 
-, 
-\emph on 
-_MPOOLSTEP, _MPOOLSTART
-\emph default 
- and the 
-\emph on 
-enum _memtypes 
-\emph default 
-holding 
-\emph on 
-_MEM_MAX
-\emph default 
- which should have been defined in <
-\emph on 
-port/support.h
-\emph default 
->.
-\emph on 
-_MPOOLS
-\emph default 
- specifies the number of 
-\emph on 
-pool_t
-\emph default 
- objects, 
-\emph on 
-_MPOOLSTEP
-\emph default 
- the 
-\emph on 
-stepp
-\emph default 
- argument to 
-\emph on 
-pool_init()
-\emph default 
-, 
-\emph on 
-_MPOOLSTART
-\emph default 
- the maximum bytesize request for the first 
-\emph on 
-pool_t
-\emph default 
-, and 
-\emph on 
-_MEM_MAX
-\emph default 
- the number of memory types supplied by the system.
- See the port-dependent section for more information on how to set these.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-mpool_destroy(mpool_t\SpecialChar ~
-*mpool)
-\emph default 
- Frees all memory currently associated with the specified 
-\emph on 
-mpool_t
-\emph default 
-, which should have previously been initialized by 
-\emph on 
-mpool_init()
-\emph default 
-, and disables the 
-\emph on 
-mpool_t
-\emph default 
-.
- Any pointers to memory which were obtained via 
-\emph on 
-_malloc()
-\emph default 
- using this pool become invalid.
- No more requests will be allowed on this 
-\emph on 
-mpool_t
-\emph default 
- unless re-initialized using 
-\emph on 
-mpool_init()
-\emph default 
-.
- TRUE is returned, or FALSE if the 
-\emph on 
-mpool_t
-\emph default 
- was already destroyed, or that the supplied pointer is NULL.
- It is also possible for this function to return FALSE without error, in
- the case where at least another task shares this 
-\emph on 
-mpool_t
-\emph default 
-.
- (See the 
-\emph on 
-TS_SHARED
-\emph default 
- flag to 
-\emph on 
-task_alloc()
-\emph default 
-).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*_malloc(mpool_t\SpecialChar ~
-*mpool,\SpecialChar ~
-int\SpecialChar ~
-memtype,\SpecialChar ~
-size_t\SpecialChar ~
-size,\SpecialChar ~
-bool\SpecialChar ~
-zero)
-\emph default 
- Attempts to allocate the requested 
-\emph on 
-size
-\emph default 
- contiguous bytes from the supplied 
-\emph on 
-mpool
-\emph default 
-, using memory of type 
-\emph on 
-memtype
-\emph default 
-.
- _MEM_ANY is valid, and will cause any available memory type to be returned.
- A pointer is returned to a memory area holding the number of bytes that
- were requested, or NULL if there is not enough memory to satisfy the request,
- or if the parameters are wrong.
- If 
-\emph on 
-zero
-\emph default 
- is TRUE, the memory area is cleared with 0x00 bytes.
- Automatic synchronization is performed if the 
-\emph on 
-mpool_t
-\emph default 
- is shared by more than one task.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*_free(void\SpecialChar ~
-*mem)
-\emph default 
- Frees back the memory to which the supplied 
-\emph on 
-mem
-\emph default 
- points, to where it belongs.
- NULL is returned.
- Automatic synchronization is performed if the 
-\emph on 
-mpool_t
-\emph default 
- is shared by more than one task.
-\layout Paragraph
-
-Kernel code
-\layout Standard
-
-Here are variants which can be used by kernel functions.
- Note that the kernel can use all the above previously mentionned functions
- as well, however for consistency it is good to use the following where
- appropriate.
- All of these, contrary to the previously described primitives, internally
- use exclusive locks as necessary to ensure the integrity of the system
- pools, so that disabling the scheduler is unnecessary:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*_kmalloc(int\SpecialChar ~
-memtype,\SpecialChar ~
-size_t\SpecialChar ~
-size,\SpecialChar ~
-bool\SpecialChar ~
-zero)
-\emph default 
- Allocates general-purpose memory from the kernel memory pool, which should
- be released using 
-\emph on 
-kfree()
-\emph default 
-.
- When a task uses this function the memory is not restored to the system
- automatically when it exists.
- Special syncronization is used internally so that it is safe to use by
- multiple tasks.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*_kfree(void\SpecialChar ~
-*mem)
-\emph default 
- Frees back to the kernel memory pools memory which has previously been
- allocated by 
-\emph on 
-kmalloc()
-\emph default 
-.
- Internal special synchronization is used.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*TMALLOC(int\SpecialChar ~
-memtype,\SpecialChar ~
-size_t\SpecialChar ~
-size)
-\emph default 
- Equivalent to calling 
-\emph on 
-kmalloc(memtype, size, FALSE);
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*TCMALLOC(int\SpecialChar ~
-memtype,\SpecialChar ~
-int\SpecialChar ~
-number,\SpecialChar ~
-size_t\SpecialChar ~
-size)
-\emph default 
- Equivalent to calling 
-\emph on 
-kmalloc(memtype, number * size, TRUE);
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*MALLOC(size_t\SpecialChar ~
-size)
-\emph default 
- Identical to calling 
-\emph on 
-kmalloc(_MEM_ANY, size, FALSE);
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*CMALLOC(int\SpecialChar ~
-number,\SpecialChar ~
-size_t\SpecialChar ~
-size)
-\emph default 
- Like calling 
-\emph on 
-_kmalloc(_MEM_ANY, number * size, TRUE);
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*FREE(void\SpecialChar ~
-*mem)
-\emph default 
- Equivalent to 
-\emph on 
-_kfree(mem);
-\emph default 
- but made to match all above macros.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*kmalloc(size_t\SpecialChar ~
-size)
-\emph default 
- Like 
-\emph on 
-MALLOC()
-\emph default 
- but implemented as an ANSI-C compliant function.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-kfree(void\SpecialChar ~
-*mem)
-\emph default 
- Counterpart to 
-\emph on 
-kmalloc()
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-pnode_t\SpecialChar ~
-*spool_alloc(u_int32_t\SpecialChar ~
-pool)
-\emph default 
- Allows to efficiently allocate a frequently used kernel object for which
- a special system pool exists.
-\emph on 
-pool
-\emph default 
- may consist of one of the 
-\emph on 
-POOL_
-\emph default 
-* names which are defined in the 
-\emph on 
-enum _syspools
-\emph default 
- in <
-\emph on 
-src/kernel/memory.h
-\emph default 
->.
- Automatic synchronization is performed.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-pnode_t\SpecialChar ~
-*spools_free(u_int32_t\SpecialChar ~
-pool,\SpecialChar ~
-pnode_t\SpecialChar ~
-*node)
-\emph default 
- Made to free a system object which was previously allocated using 
-\emph on 
-spool_alloc()
-\emph default 
-.
- Automatic synchronization is performed.
-\layout Paragraph
-
-User space tasks
-\layout Standard
-
-The following can be called by user tasks to allocate memory using their
- own memory pool, which is automatically released back to the system when
- they exit.
- They behave identically to the standard ANSI-C functions bearing the same
- name.
- They are implemented as functions rather than macros, for inclusion into
- the Xisop shared library.
- These are also safe to use in the case where more than one tasks are sharing
- an 
-\emph on 
-mpool_t
-\emph default 
- (see the 
-\emph on 
-TS_SHARED
-\emph default 
- flag to 
-\emph on 
-task_alloc()
-\emph default 
-).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*malloc(size_t\SpecialChar ~
-size)
-\emph default 
- Behaves identically to the standard ANSI-C 
-\emph on 
-malloc()
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*calloc(int\SpecialChar ~
-number,\SpecialChar ~
-size_t\SpecialChar ~
-size)
-\emph default 
- Identical to ANSI-C 
-\emph on 
-calloc()
-\emph default 
- semantics.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*realloc(void\SpecialChar ~
-*ptr,\SpecialChar ~
-size_t\SpecialChar ~
-size)
-\emph default 
- Like ANSI-C 
-\emph on 
-realloc()
-\emph default 
- semantics.
- Note that like the standard, the returned pointer can point to a new memory
- area, in which case the previous contents will have been copied over.
- The use of this function is generally discouraged against generally more
- efficient dynamic allocation techniques using linked lists.
- It is however provided for compatibility with ANSI-C.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-free(void\SpecialChar ~
-*ptr)
-\emph default 
- Again like the ANSI-C 
-\emph on 
-free()
-\emph default 
- function.
- Note that this function can also free memory which has been allocated using
-\emph on 
-tmalloc()
-\emph default 
- and 
-\emph on 
-tcmalloc()
-\emph default 
-.
-\layout Standard
-
-ANSI-C however has no concept of multiple memory types, and as such 
-\emph on 
-tmalloc()
-\emph default 
- had to be included.
-\emph on 
-free()
-\emph default 
- can be used to free back memory which they allocate still:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*tmalloc(int\SpecialChar ~
-memtype,\SpecialChar ~
-size_t\SpecialChar ~
-size)
-\emph default 
- Like 
-\emph on 
-malloc()
-\emph default 
- but allows to specify a Xisop port-dependent memory type.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*tcmalloc(int\SpecialChar ~
-memtype,\SpecialChar ~
-int\SpecialChar ~
-number,\SpecialChar ~
-size_t\SpecialChar ~
-size)
-\emph default 
- Like 
-\emph on 
-calloc()
-\emph default 
-, but can also be told the type of memory wanted.
-\layout Subsubsection
-
-A note about absolute memory allocation
-\layout Standard
-
-Xisop does not provide an allocation function which can be told the absolute
- memory location area desired.
- There are several reasons for this which this section attempts to explain.
-\layout Standard
-
-Xisop provides the necessary inter-task communications tools to prevent
- the need of using absolute memory addresses for rendez-vous among tasks.
- Moreover, it has the concept of devices, which can be left the task to
- perform synchronization among tasks which need to share a specific resource.
- Additionally, Xisop does not setup the MMU in a way to prevent user tasks
- from accessing any memory.
-\layout Standard
-
-This means that if absolute memory locations need to be reserved by the
- system, they normally should not be included into the general purpose memory
- pools.
- A user device task can then specifically handle those locations as necessary
- and provide multitasking-friendly access to them.
-\layout Standard
-
-For instance, the video memory should not be attached to the system memory
- pools by the port-specific code.
- Instead, a device task should be written and provided to allow safe access
- to the video hardware, and basic console support.
- Optionally, a handler can be provided, which even allows a higher abstraction
- to access the device.
- For instance, the device could supply basic resource allocation and access
- primitives, while the handler could support vt100 emulation over the device.
-\layout Standard
-
-In the case of a single-tasking application being developped around Xisop,
- once the scheduler is disabled there is no need for any special handling
- to access the wanted memory regions.
- The memory allocator is no longer necessary to use, even.
-\layout Standard
-
-Another consideration to realize is that if for instance video memory was
- part of the system memory pools, it could automatically be allocated by
- another task which was only requesting some memory.
- If we had support for reserved pages, then there would be no point in allocatin
-g them, also.
- Only general-purpose memory should be attached into the system.
- There exists the possibility of reserving a specific memory type for some
- memory however, if there is a need for specific regions to only be used
- by certain applications but that general purpose management primitives
- are still desired.
-\layout Standard
-
-Other than the Xisop message port system which allows tasks to share and
- synchronize arbitrary memory regions, it is possible for several tasks
- to inherently share a common memory pool, using the 
-\emph on 
-TS_SHARED
-\emph default 
- flag to 
-\emph on 
-task_alloc()
-\emph default 
-.
- This can in some circumstances be used if the memory resources are quite
- scarce (many tasks which only allocate few but various sized memory blocks
- of different memory types can waste quite a large amount of pages.
- Using the same pool would then permit the same pages to be used among the
- tasks for their similar allocation needs.
- Their allocated blocks generally consist of a page which is split in equally
- sized blocks).
- Moreover, in such a setup, one task which allocates a block of memory does
- not implicitly free it on exit, if other tasks are still running sharing
- the memory.
- Those blocks need to be explicitely freed unless all tasks exit to really
- be released back to the system.
- Moreover, special synchronization must be used by the tasks if they want
- to access the same memory addresses.
- This is usually done using an 
-\emph on 
-rwlock_t
-\emph default 
-, or disabling the scheduler temporarily.
-\layout Subsection
-
-Xisop public interrupt abstraction facilities
-\layout Standard
-
-To allow Xisop architecture-specific devices to attach interrupt handler
- hooks, and for portable code to make use of a few basic interrupt facilities
- like timers, it is a good idea to provide a few access functions to allow
- this.
- The idea is to provide a facility which allows the kernel code, or userspace
- tasks, to run a piece of code once, a certain number of times, or indefinitely,
- as part of the low-level interrupt handling code.
- It thus should be possible to add and delete their code handlers from each
- of the wanted interrupt handlers.
- To provide this multi-purpose facility, the following system was developed,
- and almost entirely consists of portable common code.
-\layout Subsubsection
-
-Internals
-\layout Standard
-
-The following structure is defined in <
-\emph on 
-common/kernel/exception.h
-\emph default 
->:
-\layout Quote
-
-
-\emph on 
-typedef struct _int_hook {
-\newline 
-\SpecialChar ~
-\SpecialChar ~
-\SpecialChar ~
-\SpecialChar ~
-pnode_t node; 
-\newline 
-\SpecialChar ~
-\SpecialChar ~
-\SpecialChar ~
-\SpecialChar ~
-hookid_t id;
-\newline 
-\SpecialChar ~
-\SpecialChar ~
-\SpecialChar ~
-\SpecialChar ~
-u_int32_t skipcount, runcount;
-\newline 
-\SpecialChar ~
-\SpecialChar ~
-\SpecialChar ~
-\SpecialChar ~
-void (*code)(hookid_t, int, void *); 
-\newline 
-\SpecialChar ~
-\SpecialChar ~
-\SpecialChar ~
-\SpecialChar ~
-void *data;
-\newline 
-} hook_t;
-\layout Standard
-
-Where 
-\emph on 
-node
-\emph default 
- is used for internal linking, 
-\emph on 
-id 
-\emph default 
-consists of a unique ID for this facility, 
-\emph on 
-skipcount
-\emph default 
- of the number of times this handler will execute before calling the 
-\emph on 
-code
-\emph default 
- hook, 
-\emph on 
-runcount
-\emph default 
- of the number of times the hook 
-\emph on 
-code
-\emph default 
- will be called before it gets automatically deleted, or 0 if it should
- execute everytime this interrupt occurs.
-\emph on 
-void\SpecialChar ~
-(*code)(hookid_t, int, void\SpecialChar ~
-*)
-\emph default 
- consists of the C function to invoke when the event occurs.
- The abstracted arguments 
-\emph on 
-void
-\emph default 
- pointer may serve any purpose the application wants.
-\emph on 
-void\SpecialChar ~
-*data
-\emph default 
- pointer to abstract user-defined data will be passed as argument to the
- called function.
- The 
-\emph on 
-hookid_t
-\emph default 
- argument will consist of the ID of the 
-\emph on 
-hook_t
-\emph default 
- into the facility which caused the call, and is made to be unique.
- The supplied 
-\emph on 
-int
-\emph default 
- argument may be useless, or can serve to determine the origin of the interrupt,
- somewhat like the 
-\emph on 
-hookid_t
-\emph default 
-, but will use a facility-specific semantics, which could include a key
- being pressed in the case of a keyboard interrupt, etc.
- The kernel uses an efficient memory 
-\emph on 
-pool_t
-\emph default 
- to internally allocate and free these automatically when hooks are attached
- and detached from facilities.
-\layout Standard
-
-The following machine-independent function is also provided so that the
- port-specific code (from assembly or C) may easily order an execution of
- all attached hooks on a facility.
- The hook ids are made to be unique so that it is safe for the one who attached
- a hook to try to delete it, assuming that if it exists in the list, it
- cannot be any other hook supplied by other code (even if it expired and
- another hook replaced it internally).
- This consists of an interface for the port, not of the general user interface
- to the facilities:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-facility_exechooks(u_int32_t\SpecialChar ~
-facility,\SpecialChar ~
-int\SpecialChar ~
-origin)
-\emph default 
- executes all attached code hooks of the specified 
-\emph on 
-facility
-\emph default 
-, sequencially (if any).
- This means that for each existing hook, the corresponding function is called
- if it's 
-\emph on 
-skipcount
-\emph default 
- is 0, or 
-\emph on 
-skipcount
-\emph default 
- is simply decreased by 1 otherwise.
- When the hook is to be called, it is passed the corresponding user data
- pointer (which can be NULL) to it, the 
-\emph on 
-hookid_t
-\emph default 
- id for the hook, and 
-\emph on 
-origin
-\emph default 
- into the 
-\emph on 
-int
-\emph default 
- argument.
- The hook is then evaluated for expiration if 
-\emph on 
-runcount
-\emph default 
- was non-zero at insertion with 
-\emph on 
-hook_attach()
-\emph default 
-, and automatically destroyed if it expires.
- The caller should normally disable the interrupt associated with the facility
- temporarily before calling this function, however the associated 
-\emph on 
-facility_t
-\emph default 
- internally uses an 
-\emph on 
-_rlock_t
-\emph default 
- to prevent self-recursion, lock which is also used by 
-\emph on 
-hook_attach()
-\emph default 
- and 
-\emph on 
-hook_detach()
-\emph default 
- for safety.
- This function is made for the port-specific code to call when the interrupt
- this facility is concerned with occurs.
- This function is dependent on 
-\emph on 
-_FACILITY_MAX
-\emph default 
- and the 
-\emph on 
-enum _facilities
-\emph default 
- which are port-specific in <
-\emph on 
-port/support.h
-\emph default 
->.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-facilities_init(void)
-\emph default 
- is provided to ease initialization of the system facility arrays from the
- port-specific code.
- This function depends on the port-specific 
-\emph on 
-_FACILITY_MAX
-\emph default 
- and the 
-\emph on 
-enum _facilities
-\emph default 
- defined in <
-\emph on 
-port/support.h
-\emph default 
->.
- More informaton on port-specific initialization is provided in a next chapter.
-\layout Standard
-
-Decision was made to provide the above functions even though their functionality
- is simple for a few reasons.
- It prevents code duplication among ports, minimises assembly sections in
- machine-dependent sections, and they are known to work, providing the required
- functionality.
- Being abstracted, their internals may change over time affecting all ports
- simultaneously without requireing changes in the machine-specific sections.
- Moreover, they use an internal memory 
-\emph on 
-pool_t
-\emph default 
- per 
-\emph on 
-facility_t
-\emph default 
- for efficiency.
- Once initialized, those will never need to query the system page primitives,
- and are thus very efficient, as well as safe to use from interrupt context
- without special handling.
-\layout Standard
-
-Because these facilities are transparent to the Xisop microkernel itself,
- and are provided by port-specific code, although driven by common portable
- code, the interrupt sources are not required to internally correspond to
- actual hardware interrupts.
- The port-specific code is free to provide the wanted interrupt sources
- and facilities in the manner it wishes.
- As such they can be used for various hardware and sotfware event types.
-\layout Subsubsection
-
-User interface
-\layout Standard
-
-Here is now described the kernel user interface to manipulate custom interrupt
- hooks on the provided facilities.
- These are also machine-independent.
- They were implemented around 
-\emph on 
-_rlock_t
-\emph default 
- and 
-\emph on 
-pool_t
-\emph default 
- primitives in a way to make it possible for userland to access their functional
-ity without the need for system call traps.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-hookid_t\SpecialChar ~
-hook_attach(u_int32_t\SpecialChar ~
-facility, u_int32_t\SpecialChar ~
-skipcount, u_int32_t\SpecialChar ~
-runcount,
- void\SpecialChar ~
-(*code)(hookid_t,\SpecialChar ~
-int,\SpecialChar ~
-void\SpecialChar ~
-*), void\SpecialChar ~
-*data)
-\emph default 
- Allows to append or insert a user supplied code hook to the wanted interrupt
- facility.
- The 
-\emph on 
-facility
-\emph default 
- argument specifies what type of exception, trap or interrupt is wanted,
- and is port-specific.
- An example would be 
-\emph on 
-_FACILITY_VBLANK
-\emph default 
-.
-\emph on 
-code
-\emph default 
- specifies which function to call as the user hook handler, which should
- never be NULL.
-\emph on 
-data
-\emph default 
- points to an optional user data block which will be passed back when calling
- the function handler, and can be NULL.
- The argument of type 
-\emph on 
-hookid_t
-\emph default 
- which will be passed will consist of the unique ID representing this 
-\emph on 
-hook_t
-\emph default 
- into the 
-\emph on 
-facility
-\emph default 
-, while the 
-\emph on 
-int
-\emph default 
- argument, which is facility-specific, could serve to determine the origin
- of the event if the facility serves several.
- The return value is 0 in the case of an error (unknown public facility),
- or a unique ID which can be used to eventually delete that particular hook.
- This is required to not correspond to the hook function address, since
- multiple hooks may call the same function if wanted.
- This ID is always unique to this facility.
- It is safe to attach a code hook function which can expire and then attempt
- to remove it using the supplied 
-\emph on 
-hookid_t
-\emph default 
-.
- If it expired and another hook now uses the same 
-\emph on 
-hook_t
-\emph default 
- address, it's 
-\emph on 
-hookid_t
-\emph default 
- will still be different.
- The semantics of 
-\emph on 
-skipcount
-\emph default 
- and 
-\emph on 
-runcount
-\emph default 
- are explained in the internals above.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-hook_detach(u_int32_t\SpecialChar ~
-facility,\SpecialChar ~
-hookid_t\SpecialChar ~
-id)
-\emph default 
- Permits to remove a user supplied hook on the wanted 
-\emph on 
-facility
-\emph default 
-, with the specfied 
-\emph on 
-id
-\emph default 
-.
- Returns TRUE if it could find and delete the hook, or FALSE if the hook
- did not exist, or no longer does (it may have expired).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-facility_disable(u_int32_t\SpecialChar ~
-facility)
-\emph default 
- Disables all hooks of the specified facility temporarily.
- They cannot expire during the period they are suspended, and none will
- be executed, even when the interrupt source occurs.
- It does not disable the interrupt source.
- This system is recursive, in that the exact same number of calls to 
-\emph on 
-facility_enable()
-\emph default 
- must be made to re-enable the facility.
- Note that it is safe to attach and detach hooks from a facility at any
- time, and that this function is only provided as a feature.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-facility_enable(u_int32_t\SpecialChar ~
-facility)
-\emph default 
- Re-enables the specified facility which was previously suspended using
-\emph on 
-facility_disable()
-\emph default 
-, if the 
-\emph on 
-facility_t
-\emph default 
- internal 
-\emph on 
-_rlock_t
-\emph default 
- reaches 0 (that is all previous calls to 
-\emph on 
-facility_disable()
-\emph default 
- were matched by a 
-\emph on 
-facility_disable()
-\emph default 
-).
-\layout Subsubsection
-
-Common facilities
-\layout Standard
-
-Not all ports have all these facilities, and some may provide more.
- However, this consists of a guide so that facilities which are intended
- to provide the same functionality on the various architectures bear the
- same name.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_SCHEDTIMER
-\emph default 
- This is the only facility which must be available on all ports.
- It usually executes at intervals governed by 
-\emph on 
-_SCHEDTIMER_HZ
-\emph default 
-, a frequency defined in instances per second (hertz), which is defined
- in <
-\emph on 
-port/support.h
-\emph default 
->.
- Systems which only comport one hardware timer source will at least always
- have this timer facility available for multiple uses, although internally
- used by the scheduler.
- Disabling the scheduler does not disable the timer facility, as the scheduler
- lock consists of an 
-\emph on 
-_rlock_t
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_KEYBOARD
-\emph default 
- As the name implies, this facility is concerned with keyboard key presses.
- The key code is usually returned in the 
-\emph on 
-int
-\emph default 
- argument when calling the attached hooks.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_VBLANK
-\emph default 
- This facility is very useful for graphic-oriented software which need to
- synchronize operations with the video refresh rate.
- The frequency of a vertical blank interrupt varies with the underlaying
- hardware, but usually consists of 50Hz for PAL (europe) and 60Hz for NTSC
- (american) systems.
- This is very useful to implement double buffering, and can also be used
- to synchronize audio events like music and sound effects with animations.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_TRAP
-\emph default 
-* These type of facilities can be directly tied to user traps which may
- remain available, and associated to a related 
-\emph on 
-_cause()
-\emph default 
- function to allow user tasks to both attach handlers to receive those events
- and call 
-\emph on 
-_cause()
-\emph default 
- to trigger such events.
- However, because of the Xisop 
-\emph on 
-sys_custom()
-\emph default 
- system call, the use of such facilities become questionable.
-\emph on 
-XXX
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_FLOPPYSYNC
-\emph default 
- Triggered when a floppy drive notifies that it found the sync code of a
- track.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_FLOPPYBLOCK
-\emph default 
- Triggered when the floppy drive finished reading a requested block to memory.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_AUDIO
-\emph default 
- Notification that an audio channel finished playing a sample, or starts
- looping back the supplied sample buffer again.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_BLITTERREADY
-\emph default 
- Notification by a parallel hardware blitter that it is done with the requested
- operations and may now be ordered new instructions again.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_COPPER
-\emph default 
- A hardware raster parrallel blitter originated interrupt
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_SERIAL
-\emph default 
- A generic serial interrupt
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_SERIALRBF
-\emph default 
- A serial Read Buffer Full interrupt
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_FACILITY_SERIALTBE
-\emph default 
- A serial Transmit Buffer Empty interrupt
-\layout Standard
-
-Many other types of facilities may exist, although what should be taken
- as an example consists of the clear names that they are given, which directly
- reference to their origin as much as possible, while attempting to avoid
- cryptic names such as KBD for keyboard, etc.
- Where required, the label can be long enough as long as it remains meaningful.
-\layout Subsection
-
-Kernel statistics
-\layout Standard
-
-The 
-\emph on 
-src/common/kernel/statistic.
-\emph default 
-(
-\emph on 
-c
-\emph default 
-|
-\emph on 
-h
-\emph default 
-) module defines primitives for statistic counters.
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsection
-
-Xisop binaries and executables
-\layout Standard
-
-The Xisop kernel currently has no ELF or a.out relocatable executable loader,
- and no custom format was implemented, which would require a GCC ld BFD
- backend to be written.
- This means that at current time, all the shared libraries, devices, handlers
- and user tasks need to be started by the kernel at startup.
- This is easily done however, but prevents the microkernel from using all
- it's features of attaching required components at runtime as wanted, although
- it was designed to eventually be able to do so efficiently.
- It however currently allows Xisop to be useable in embedded systems which
- have defined components, like for monolithic kernels.
-\layout Subsection
-
-Xisop devices
-\layout Standard
-
-Xisop devices generally consist of a medium-level backend to hardware-assisted
- services, such as keyboard input, tty output, RS-232 communication, etc.
- As such, they are generally architecture-dependent.
- Of course, machine-independent devices may be written as wanted, where
- the high-level handler interface is considered unadequate and that shared
- access to some kind of ressource is wanted, however.
-\layout Standard
-
-The Xisop devices are implemented around the message port system.
- There were two main reasons which determined this decision compared to
- using a shared library type system.
- First, the message receiving responsiveness and speed can be determined
- by the task priority, which allows the administrator to decide which devices
- and tasks to prioritize over others.
- Secondly, the message passing system already provides reliable FIFO queuing,
- and each message/request can be replied to when wanted, allowing a device
- to easily serve resources in a multitasking-friendly, asynchroneous manner
- to the simultaneous requesters.
-\layout Standard
-
-A device is thus implemented by a task, which decides to attach a system
- device node and then takes the responsibility to serve the expected requests.
- Each task may only attach one device to the system lists, and has to specify
- the device name and version which are used for other tasks to open the
- device.
- This means that a device name may have several simultaneous versions running
- on the system.
-\layout Standard
-
-Of course, there are cases where only a single device may control a specific
- hardware resource for instance, and in this case the versionning system
- becomes less useful, in which case version 0 is usually used.
- However, the version may still be useful if the various versions of the
- device had changes to the user interface.
- In this case, using the version is still useful, as opening using the wrong
- version (the one a task expects) will at least always fail cleanly with
- an error, rather than leaving the task to open a device which does not
- act as expected when sending requests.
-\layout Subsubsection
-
-User interface
-\layout Standard
-
-Here are described the device interface functions.
- Let's first present the functions which are intended for client tasks to
- access device server ones:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-device_t\SpecialChar ~
-*device_open(const\SpecialChar ~
-char\SpecialChar ~
-*name,\SpecialChar ~
-u_int32_t\SpecialChar ~
-version,\SpecialChar ~
-u_int32_t\SpecialChar ~
-unit)
-\emph default 
- Allows the task to open the unit number 
-\emph on 
-unit
-\emph default 
- of device 
-\emph on 
-name
-\emph default 
- of version 
-\emph on 
-version
-\emph default 
-.
- NULL is returned on failure, which can occur because of lack of memory,
- or if the specified device name of the specified version does not exist.
- Otherwise, a 
-\emph on 
-device_t
-\emph default 
- handle pointer is returned, which may then be used at 
-\emph on 
-iorequest_init()
-\emph default 
-.
- Device names are case-sensitive.
- If the task exists and that open devices have not been explicitely closed,
- the kernel automatically closes them.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-device_t\SpecialChar ~
-*device_close(device_t\SpecialChar ~
-*handle)
-\emph default 
- Closes a device handle which previously was opened using 
-\emph on 
-device_open()
-\emph default 
-.
- Always returns NULL.
- Any 
-\emph on 
-iorequest_t
-\emph default 
- associated to this 
-\emph on 
-device_t
-\emph default 
- may not be used anymore, as it becomes invalid, unless it be reinitialized
- again using 
-\emph on 
-iorequest_init()
-\emph default 
- using a new 
-\emph on 
-device_t
-\emph default 
- handle.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-iorequest_init(iorequest_t\SpecialChar ~
-*message,\SpecialChar ~
-device_t\SpecialChar ~
-*handle,\SpecialChar ~
-port_t\SpecialChar ~
-*replyport)
-\emph default 
- Initializes an 
-\emph on 
-iorequest_t
-\emph default 
-\emph on 
-message
-\emph default 
-, which is necessary to use other 
-\emph on 
-iorequest_
-\emph default 
-*
-\emph on 
-()
-\emph default 
- functions to perform device requests.
-\emph on 
-handle
-\emph default 
- specifies the 
-\emph on 
-device_t
-\emph default 
- which will serve requests for this message during future requests, and
-\emph on 
-replyport
-\emph default 
- of a generally 
-\emph on 
-iorequest_t
-\emph default 
--specific private port which was previously created, through which request
- result messages will be sent back to us by the device.
- The 
-\emph on 
-iorequest_t
-\emph default 
- buffer is the responsibility of the task, just like 
-\emph on 
-port_t
-\emph default 
-\emph on 
-message_t
-\emph default 
- are.
- Returns TRUE on success, or FALSE on failure (invalid arguments or out
- of memory).
- The device may optionally internally allocate device-specific additional
- data which will then attach to the 
-\emph on 
-iorequest_t
-\emph default 
-.
- These will however be allocated on the current task's memory pool, and
- are therefore released automatically if the task exists.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-iorequest_destroy(iorequest_t\SpecialChar ~
-*message)
-\emph default 
- Invalidates the 
-\emph on 
-iorequest_t
-\emph default 
-\emph on 
-message
-\emph default 
- which was previously initialized using 
-\emph on 
-iorequest_init()
-\emph default 
-.
- As devices may internally allocate device-specific additional data and
- attach it to an 
-\emph on 
-iorequest_t
-\emph default 
- at initialization, a task should call this function when it no longer needs
- the 
-\emph on 
-iorequest_t
-\emph default 
-.
- Of course, if the task exists, the resources are automatically released
- back to the system, however.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-iorequest_sync(iorequest_t\SpecialChar ~
-*message)
-\emph default 
- Permits to send a synchroneous request to a device, via 
-\emph on 
-message
-\emph default 
-.
- This means that the task is suspended until the request completes.
- The reply result is also automatically extracted from the reply port associated
- to the 
-\emph on 
-iorequest_t
-\emph default 
-.
- Before sending a request, some fields of the 
-\emph on 
-iorequest_t
-\emph default 
- message should be set.
- When it completes, the result fields will have been set.
- Both can have device-dependent semantics, although there is generally a
- standard, which is described in the internals section.
- Returns TRUE if the request could be sent, or FALSE if there was an internal
- problem (invalid 
-\emph on 
-message
-\emph default 
-, or no longer existing device).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-iorequest_async(iorequest_t\SpecialChar ~
-*message)
-\emph default 
- Very similar to 
-\emph on 
-iorequest_sync()
-\emph default 
-, but permits to launch the request without waiting until it completes,
- performing an asynchroneous request.
- Upon completion, the device will internally 
-\emph on 
-port_reply()
-\emph default 
- into the reply port associated with 
-\emph on 
-message
-\emph default 
-, and the task is then responsible for extracting the reply message from
- the reply port.
- This allows to launch several asynchroneous requests and to monitor signals
- or ports to detect when they occur.
- For instance, a task may launch an asynchroneous request to read one character,
- and when the request completes, specifying that data exists to read.
- It can then send synchroneous requests to read larger blocks until no more
- data is available, in which case it may then again send an asynchroneous
- request and resume normal activity.
- TRUE is returned if the request could be launched, or FALSE if it failed
- (invalid 
-\emph on 
-message
-\emph default 
- or no longer existing device).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-iorequest_abort(iorequest_t\SpecialChar ~
-*message)
-\emph default 
- If 
-\emph on 
-message
-\emph default 
- currently consists of an asynchroneous request which was made using 
-\emph on 
-iorequest_async()
-\emph default 
- and is still pending, an abort request is sent to cancel it.
- Like usual, the device will reply still as soon as the request could be
- aborted, and the task becomes responsible to unlink the reply message from
- the reply port associated with 
-\emph on 
-message
-\emph default 
-.
- TRUE is returned on success, or FALSE if 
-\emph on 
-message
-\emph default 
- does not consist of a currently pending asynchroneous request.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-iorequest_wait(iorequest_t\SpecialChar ~
-*message)
-\emph default 
- Waits until a currently pending (or aborted which not yet replied) asynchoneous
- request terminates, and automatically unlinks the reply message received
- through the reply port of 
-\emph on 
-message
-\emph default 
-.
- This can especially be useful after an 
-\emph on 
-iorequest_abort()
-\emph default 
-.
- Returns TRUE on success, or FALSE if 
-\emph on 
-message
-\emph default 
- is not currently a pending (or aborted which did not yet return) asynchroneous
- request.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-iorequest_pending(iorequest_t\SpecialChar ~
-*message)
-\emph default 
- Returns TRUE if 
-\emph on 
-message
-\emph default 
- currently consists of an asynchroneously pending request, or FALSE otherwise.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-iorequest_aborted(iorequest_t\SpecialChar ~
-*message)
-\emph default 
- Returns TRUE if 
-\emph on 
-message
-\emph default 
- consists of a request which just completed, but which was an asynchroneous
- request and was aborted.
-\layout Standard
-
-These utility functions, although performing the most basic Xisop device
- operations, are provided to minimize code duplication, for very simple
- synchroneous I/O.
- Normally, tasks will address requests using 
-\emph on 
-iorequest_sync()
-\emph default 
- and 
-\emph on 
-iorequest_async()
-\emph default 
- as needed, but this can be useful to have:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-ssize_t\SpecialChar ~
-device_read(iorequest_t\SpecialChar ~
-*req,\SpecialChar ~
-void\SpecialChar ~
-*buf,\SpecialChar ~
-size_t\SpecialChar ~
-len)
-\emph default 
- Similarily to unix 
-\emph on 
-read()
-\emph default 
-, reads at most 
-\emph on 
-len
-\emph default 
- bytes of data from the opened device and unit associated with 
-\emph on 
-req
-\emph default 
- into 
-\emph on 
-buf
-\emph default 
-, and returns the number of actually read bytes, or -1 on error.
- The current task is suspended until the operation completes, since 
-\emph on 
-iorequest_sync()
-\emph default 
- is internally used.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-ssize_t\SpecialChar ~
-device_write(iorequest_t\SpecialChar ~
-*req,\SpecialChar ~
-void\SpecialChar ~
-*buf,\SpecialChar ~
-size_t\SpecialChar ~
-len)
-\emph default 
- Like unix 
-\emph on 
-write()
-\emph default 
-, writes at most 
-\emph on 
-len
-\emph default 
- bytes of data from 
-\emph on 
-buf
-\emph default 
-, to the opened device and unit associated with 
-\emph on 
-req
-\emph default 
-, and returns the number of actually written bytes, or -1 on error.
- The current task is suspended until the operation completes as it internally
- uses 
-\emph on 
-iorequest_sync()
-\emph default 
-.
-\layout Subsubsection
-
-Device server interface
-\layout Standard
-
-Here follows functions which are only useful to device server tasks to call:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-device_attach(const\SpecialChar ~
-char\SpecialChar ~
-*name, u_int32_t\SpecialChar ~
-version, port_t\SpecialChar ~
-*port, void\SpecialChar ~
-(*clean)(vo
-id), bool\SpecialChar ~
-(*open)(void\SpecialChar ~
-**,\SpecialChar ~
-u_int32_t), void\SpecialChar ~
-(*close)(void\SpecialChar ~
-*,\SpecialChar ~
-u_int32_t), void\SpecialChar ~
-*(*iorini
-t)(void), void\SpecialChar ~
-(*iordestroy)(void\SpecialChar ~
-*), u_int8_t\SpecialChar ~
-flags)
-\emph default 
-
-\newline 
-Allows the current task to become a system device.
-\emph on 
-name
-\emph default 
- consists of the unique case-sensitive device name to assign to the system
- device node, which will be required to use at 
-\emph on 
-device_open()
-\emph default 
-, and will be truncated to 32 characters if longer.
-\emph on 
-version
-\emph default 
- specifies the version number to use, which will also need to match at 
-\emph on 
-device_open()
-\emph default 
-, for this device name.
-\emph on 
-port
-\emph default 
- consists of the device server's private port, through which requests should
- be sent.
-\emph on 
-flags
-\emph default 
- consists of one or combination of 
-\emph on 
-DNF_
-\emph default 
-* flags described in the header file, like 
-\emph on 
-DNF_RESIDENT
-\emph default 
- which tells Xisop to never cause the device task to exit if there exist
- no more client open instances.
- The various function pointers which must be supplied are explained below:
-\begin_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-(*clean)(void)
-\emph default 
- is a function which the device task can provide for Xisop to call when
- no more client open instances exist for this device, unless the device
- is resident (and 
-\emph on 
-flags
-\emph default 
- comported 
-\emph on 
-DNF_RESIDENT
-\emph default 
- at device creation).
- This function is responsible to restore the hardware which this device
- may have been serving to a consistant and known state.
- It will also be called automatically by Xisop when the task exits normally.
- Note that 
-\emph on 
-clean()
-\emph default 
- should not comport any special function to cause the task to end.
- Xisop will send a 
-\emph on 
-SIGTERM
-\emph default 
- signal when the task should do so.
- If the task exits by itself, 
-\emph on 
-clean()
-\emph default 
- will be called automatically nevertheless.
- Because this function may be called under the context of any other task,
- it should not expect to execute under the device's task memory pool (and
- therefore should normally not call allocation functions).
- It is possible to specify NULL for this function if the device has no need
- for any special cleanup function.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-(*open)(void\SpecialChar ~
-**udata,\SpecialChar ~
-u_int32_t\SpecialChar ~
-unit)
-\emph default 
- All devices are required to provide this function.
- It's purpose is to validate if 
-\emph on 
-unit
-\emph default 
- can be opened (some devices limit the number of open instances of a unit,
- to protect their resources), and to optionally allocate any needed device-speci
-fic data which it may need to attach to 
-\emph on 
-device_t
-\emph default 
- nodes.
-\emph on 
-open()
-\emph default 
- is called at each 
-\emph on 
-device_open()
-\emph default 
- function instance called on this device.
- It is expected to return FALSE if it refuses to open the specified 
-\emph on 
-unit
-\emph default 
- or if it cannot allocate any required resources, or TRUE on success.
- If the task allocates data which is needed to be attached to the 
-\emph on 
-device_t
-\emph default 
- handle, it should supply the address of the allocated data block into the
- supplied 
-\emph on 
-udata
-\emph default 
-.
- It should set NULL there otherwise.
- Although the device may at it's discretion maintain counters on the number
- of currently opened units, etc, Xisop will automatically send a SIGTERM
- to the device task if it is non-resident and that there exist no more openers.
- Note that this function is called under the context of the task which calls
-\emph on 
-device_open()
-\emph default 
-.
- As such, the memory allocations, such as the optional 
-\emph on 
-udata
-\emph default 
- block will be automatically freed when the other task ends, not ours.
- For this reason, the function can use 
-\emph on 
-malloc()
-\emph default 
- and companions safely, but should not use lower-level Xisop kernel allocation
- primitives.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-(*close)(void\SpecialChar ~
-*udata,\SpecialChar ~
-u_int32_t\SpecialChar ~
-unit)
-\emph default 
- This function is also required for all device tasks to provide, and is
- called by 
-\emph on 
-device_close()
-\emph default 
- on a 
-\emph on 
-device_t
-\emph default 
- handle which was previously associated to this task by 
-\emph on 
-device_open()
-\emph default 
-.
- The function is responsible for calling 
-\emph on 
-free()
-\emph default 
- on the supplied 
-\emph on 
-udata
-\emph default 
- pointer if needed, and to perform the necessary device-specific cleanup
- required when a device handle closes.
-\emph on 
-unit
-\emph default 
- specifies the unit which was opened by this handle.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*(*iorinit)(void)
-\emph default 
- Devices may optionally provide this function to allocate 
-\emph on 
-iorequest_t
-\emph default 
- message specific data which it might need, very similarily to 
-\emph on 
-open()
-\emph default 
- which can attach data to a 
-\emph on 
-device_t
-\emph default 
- handle.
- NULL can be supplied if there is no need for 
-\emph on 
-iorequest_t
-\emph default 
- specific extention data.
- This function is called under the context of the task calling 
-\emph on 
-iorequest_init()
-\emph default 
- and as such no Xisop low-level allocation functions should be called.
- The function may allocate the data block with 
-\emph on 
-malloc()
-\emph default 
-, initialize it and return a pointer to it, or NULL on failure (out of memory).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-(iordestroy)(void\SpecialChar ~
-*udata)
-\emph default 
- May also be supplied NULL if NULL was supplied for 
-\emph on 
-iorinit()
-\emph default 
-.
- Otherwise, this function is responsible to 
-\emph on 
-free()
-\emph default 
- the supplied 
-\emph on 
-udata
-\emph default 
-, which corresponds to a block of memory which was returned by a previous
-\emph on 
-iorinit()
-\emph default 
- call.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-iorequest_satisfy(iorequest_t\SpecialChar ~
-*message,\SpecialChar ~
-bool\SpecialChar ~
-result)
-\emph default 
- Is a useful utility function to set the main request success result code
- and reply to the task that it has completed.
-\layout Standard
-
-Various macros of interest may be used by device tasks:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*DEVICEHANDLE_UDATA(device_t\SpecialChar ~
-*handle)
-\emph default 
- Returns the 
-\emph on 
-udata
-\emph default 
- pointer associated with the supplied 
-\emph on 
-device_t
-\emph default 
-\emph on 
-handle
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-*IOREQUEST_UDATA(iorequest_t\SpecialChar ~
-*message)
-\emph default 
- Returns the 
-\emph on 
-udata
-\emph default 
- pointer associated with the supplied 
-\emph on 
-iorequest_t message
-\emph default 
-.
-\layout Subsubsection
-
-Internals
-\layout Standard
-
-This system based upon the Xisop message ports system and the previously
- described functions permit to open or provide devices, and to communicate
- requests from the client-side and completion from the server-side, through
- a special message, the 
-\emph on 
-iorequest_t
-\emph default 
-.
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsection
-
-Xisop handlers
-\layout Standard
-
-Handlers provide a higher-level abstraction to devices or resources.
- It should be noted that unlike devices, these are implemented in the form
- of a standard shared library format.
- This means that devices are usually a nice abstraction to mount handlers
- on, as devices naturally perform the queuing, etc.
-\emph on 
-XXX
-\layout Subsection
-
-Xisop shared libraries
-\layout Standard
-
-The concept of Xisop shared libraries is both very simple, and unusual.
- It is important that all functions a library provides publically be reentrant.
- Opening a library basically obtains the pointer to a structure which is
- necessary to access it's function pointers.
- As such, only one resident copy is required for all applications, and new
- applications can 
-\begin_inset Quotes eld
-\end_inset 
-
-attach
-\begin_inset Quotes erd
-\end_inset 
-
- the libraries they need as required.
- The system keeps track of how many times it is currently being open by
- various tasks, and can therefore know when the library should be expunged
- from memory.
- Obviously, when a library is requested which is not currently in RAM, it
- should be loaded in the system from disk.
-\layout Standard
-
-Each library may have concurrent versions on the same system, in memory
- and on disk.
- When an application requests access to a library, it optionally specifies
- the expected version, without which the latest is assumed.
- This way, it is possible for the administrator to get rid of the obsolete
- libraries but only after making sure that no applications require them
- anymore.
- While software is being developped, it becomes possible to have concurrent
- versions of applications each using their respectively related material.
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsubsection
-
-The Xisop library
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsection
-
-Xisop system calls
-\layout Standard
-
-System calls are different than normal functions in that they allow userspace
- tasks to execute instructions which are normally only allowed to call in
- supervisor mode, or in kernel space.
- Moreover, system calls are currently uninterruptible in Xisop, which means
- that the task is guaranteed to not be preempted while executing a system
- call function, until it returned.
- These are internally implemented using processor traps, by the port-specific
- code.
- However, the system call functions themselves are portable and part of
- the Xisop common code.
- Because Xisop does not use MMU facilities, system calls are very fast to
- execute compared to on unix systems.
- Xisop design attempts to require the less of these possible however, because
- they also disable the scheduler when executing.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-struct\SpecialChar ~
-xisop_root\SpecialChar ~
-*sys_getroot(void)
-\emph default 
- Permits a task to obtain the address of the main Xisop control structure,
- where system lists are stored.
- Obviously, if a task uses this information in any way, it has to be careful
- not to disrupt Xisop activities.
- It is recommended to disable the scheduler and/or interrupts where required
- to access the information which that structure provides.
- It is made for people who know Xisop inside out only.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-sys_int_disable(void)
-\emph default 
- This internally calls 
-\emph on 
-_splhigh()
-\emph default 
- which ensures to mask all interrupts, including that of the preemptive
- scheduler.
- Precautions should be made about the calls used similarly to when disabling
- the scheduler.
- However, this call permits a task to completely take control over Xisop.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-sys_int_enable(void)
-\emph default 
- Internally calling 
-\emph on 
-_spl0()
-\emph default 
-, this re-enables all interrupts.
-\emph on 
-XXX
-\emph default 
- heh actually, can the 
-\emph on 
-_syscall()
-\emph default 
- trap actually occur after a 
-\emph on 
-sys_int_disable()
-\emph default 
-? Will need to check this out.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-sys_idle(void)
-\emph default 
- Permits to suspend the processor until the next trap, interrupt or exception
- occurs.
- This internally calls the 
-\emph on 
-_idle()
-\emph default 
- processor-specific function.
- This is mostly used by Xisop 
-\emph on 
-main()
-\emph default 
- which is returned control to when no tasks are currently on the ready queue.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-sys_custom(void\SpecialChar ~
-*res,\SpecialChar ~
-void\SpecialChar ~
-(*func)(void\SpecialChar ~
-*,\SpecialChar ~
-void\SpecialChar ~
-*),\SpecialChar ~
-void\SpecialChar ~
-*args)
-\emph default 
- A very special system call, allows user tasks to execute arbitrary code
- in supervisor mode, uninterruptibly (scheduler will not preempt, but interrupts
- can still take place).
-\emph on 
-func
-\emph default 
- specifies the function to call, which will be passed 
-\emph on 
-res
-\emph default 
- as the first argument and 
-\emph on 
-args
-\emph default 
- as the second argument, which can be used by the function to acquire parameters
- and return results.
-\emph on 
-res
-\emph default 
- and 
-\emph on 
-args
-\emph default 
- can be NULL when they are not needed.
- Because Xisop attempts to be more useful to the programmer than to secure
- the kernel against userland, this was beleived to be a very useful function,
- where user tasks can create their custom system calls as required.
-\layout Subsection
-
-Xisop general programming interfaces
-\layout Standard
-
-In an attempt to keep the code unified and clean, multipurpose interfaces
- were provided.
-\layout Subsubsection
-
-Byte alignment macros
-\layout Standard
-
-In 
-\emph on 
-<common/types.h>
-\emph default 
- the following macros are provided for byte alignment.
-\layout Standard
-
-These macros permit object size related byte alignment:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-size_t\SpecialChar ~
-OALIGN_CEIL(size_t\SpecialChar ~
-v,\SpecialChar ~
-o)
-\emph default 
-\emph on 
-o
-\emph default 
--aligns 
-\emph on 
-v
-\emph default 
-.
- This macro rounds 
-\emph on 
-v
-\emph default 
- to the nearest larger unit as required.
-\emph on 
-o
-\emph default 
- should be any native C or custom structure type, to which 
-\emph on 
-v
-\emph default 
- should be aligned relative to.
-\emph on 
-v
-\emph default 
- is not modified, the new value is returned.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-size_t\SpecialChar ~
-OALIGN_FLOOR(size_t\SpecialChar ~
-v,\SpecialChar ~
-o)
-\emph default 
-\emph on 
-o
-\emph default 
--aligns 
-\emph on 
-v
-\emph default 
-.
- Unlike 
-\emph on 
-OALIGN_CEIL()
-\emph default 
- this macro rounds to the nearest smaller unit as required.
-\layout Standard
-
-And these macros permit byte size related alignment:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-size_t\SpecialChar ~
-BALIGN_CEIL(size_t\SpecialChar ~
-v,\SpecialChar ~
-size_t\SpecialChar ~
-s)
-\emph default 
- This macro aligns 
-\emph on 
-v
-\emph default 
- to the nearest larger unit relative to 
-\emph on 
-s
-\emph default 
- size as required.
-\emph on 
-v
-\emph default 
- is not modified, the new value is returned.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-size_t\SpecialChar ~
-BALIGN_FLOOR(size_t\SpecialChar ~
-v,\SpecialChar ~
-size_t\SpecialChar ~
-s)
-\emph default 
- Very similar to 
-\emph on 
-BALIGN_CEIL()
-\emph default 
-, but rounds 
-\emph on 
-v
-\emph default 
- to the nearest smaller unit relative to 
-\emph on 
-s
-\emph default 
- size as required.
-\layout Subsubsection
-
-Byte order manipulation macros
-\layout Standard
-
-In 
-\emph on 
-<common/types.h>
-\emph default 
- the following macros are provided for byte order/endian conversions.
- These are most useful for network Remote Procedure Call implementations,
- as well as for binary file formats which can be in network order so that
- multiple architectures may easily use the same file format.
- Depending on the native host byte order (the 
-\emph on 
-_ARCH_BIG_ENDIAN
-\emph default 
- and 
-\emph on 
-_ARCH_LITTLE_ENDIAN
-\emph default 
- definitions defined by processor-specific code), these will perform no
- action where no conversion is necessary.
- The network order should be used for transferring over networks or writing
- to binary files, and actually corresponds to the native host byte order
- on big endian architectures.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-u_int16_t\SpecialChar ~
-BYTEORDER_NETWORK16(u_int16_t)
-\emph default 
- Converts the specified 16-bit word to network order for sending through
- the network or writing to a binary file.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-u_int16_t\SpecialChar ~
-BYTEORDER_HOST16(u_int16_t)
-\emph default 
- Converts the specified network order 16-bit word to native host order after
- reading from a binary file or receiving through the network.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-u_int32_t\SpecialChar ~
-BYTEORDER_NETWORK32(u_int32_t)
-\emph default 
- Converts the specified 32-bit word to network order for sending through
- the network or writing to a binary file.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-u_int32_t\SpecialChar ~
-BYTEORDER_HOST32(u_int32_t)
-\emph default 
- Converts the specified network order 32-bit word to native host order after
- reading from a binary file or receiving through the network.
-\layout Subsubsection
-
-Doubly linked lists
-\layout Standard
-
-These macros, as well as the 
-\emph on 
-list_t
-\emph default 
- and 
-\emph on 
-node_t
-\emph default 
- types are defined in 
-\emph on 
-<common/types.h>
-\emph default 
- and 
-\emph on 
-<common/kernlib/list.h>
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-DLIST_INIT(list_t\SpecialChar ~
-*list)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-DLIST_APPEND(list_t\SpecialChar ~
-*list,\SpecialChar ~
-node_t\SpecialChar ~
-*node)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-DLIST_INSERT(list_t\SpecialChar ~
-*list,\SpecialChar ~
-node_t\SpecialChar ~
-*node)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-DLIST_INSERTAT(list_t\SpecialChar ~
-*list,\SpecialChar ~
-node_t\SpecialChar ~
-*atnode,\SpecialChar ~
-node_t\SpecialChar ~
-*node)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-DLIST_SWAP(list\SpecialChar ~
-t\SpecialChar ~
-*dstlist,\SpecialChar ~
-list_t\SpecialChar ~
-*srclist,\SpecialChar ~
-node_t\SpecialChar ~
-*srcnode,\SpecialChar ~
-bool\SpecialChar ~
-insert)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-DLIST_UNLINK(list_t\SpecialChar ~
-*list,\SpecialChar ~
-node_t\SpecialChar ~
-*node)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-u_int32_t\SpecialChar ~
-DLIST_NODES(list_t\SpecialChar ~
-*list)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-node_t\SpecialChar ~
-*DLIST_TOP(list_t\SpecialChar ~
-*list)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-node_t\SpecialChar ~
-*DLIST_BOTTOM(list_t\SpecialChar ~
-*list)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-node_t\SpecialChar ~
-*DLIST_NEXT(node_t\SpecialChar ~
-*node)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-node_t\SpecialChar ~
-*DLIST_PREV(node_t\SpecialChar ~
-*node)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-DLIST_FOREACH(list_t\SpecialChar ~
-*list,\SpecialChar ~
-node_t\SpecialChar ~
-*iterator)
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsubsection
-
-Hash based fast lookup tables
-\layout Standard
-
-The prototypes and types for these are defined in 
-\emph on 
-<common/types.h>
-\emph default 
- and 
-\emph on 
-<common/kernlib/hash.h>
-\emph default 
-.
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsubsection
-
-FIFO (First In, First Out) buffers
-\layout Standard
-
-These macros as well as the default FIFO types are defined in 
-\emph on 
-<common/types.h>
-\emph default 
- and 
-\emph on 
-<common/kernlib/fifo.h>
-\emph default 
-.
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsubsection
-
-LIFO (Last In, First Out / Stack) buffers
-\layout Standard
-
-These macros as well as the default LIFO types are defined in 
-\emph on 
-<common/types.h>
-\emph default 
- and 
-\emph on 
-<common/kernlib/lifo.h>
-\emph default 
-.
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsection
-
-Xisop source tree organization
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-doc/
-\emph default 
- This directory holds this file, as well as various notes of interest
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/
-\emph default 
- Where all source resides
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/common/
-\emph default 
- All machine-independent Xisop source
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/common/kernel/
-\emph default 
- Xisop kernel main code
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/common/kernlib/
-\emph default 
- Xisop kernel main machine-independent libraries
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/common/library/
-\emph default 
- Xisop machine-independent shared libraries
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/common/device/
-\emph default 
- Xisop machine-independent devices
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/common/handler/
-\emph default 
- Xisop machine-independent handlers
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/common/task/
-\emph default 
- Xisop machine-independent resident tasks
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/processors/
-\emph default 
- Holds all processor-specific code
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/processors/m68k/
-\emph default 
- The Motorola m68k support (MC68000L8/L10)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/processors/m68k/kernlib/
-\emph default 
- m68k specific replacement functions for wanted standard machine-independent
- kernlib ones (optional)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/ports/
-\emph default 
- Holds all port-specific code, including boot loaders
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/ports/amiga/
-\emph default 
- The Amiga port of Xisop code resides here
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/ports/amiga/kernlib/
-\emph default 
- Amiga-specific replacement functions for wanted standard machine-independent
- kernlib ones (optional)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/ports/amiga/boot/
-\emph default 
- The Amiga-specific code to generate a bootable kernel
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/ports/amiga/library/
-\emph default 
- Amiga-specific shared libraries (optional)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/ports/amiga/device/
-\emph default 
- Amiga-specific devices (optional)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/ports/amiga/handler/
-\emph default 
- Amiga-specific handlers (optional)
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/ports/amiga/task/
-\emph default 
- Amiga-specific resident tasks (optional)
-\layout Subsection
-
-The build process
-\layout Standard
-
-Here is described the way the Xisop source is built to create a binary kernel
- image.
-\emph on 
-/bin/sh
-\emph default 
- is also assumed to exist for the building process.
- The convention for the script names are as follows:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/generic_makedefs.sh
-\emph default 
- contains various sh functions and variables assigned to local utilities
- which are required by all 
-\emph on 
-clean.sh
-\emph default 
- scripts, and the main 
-\emph on 
-src/make.sh
-\emph default 
- script.
- Those scripts 
-\emph on 
-source
-\emph default 
- this file to obtain the common information.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/makedefs.sh
-\emph default 
- consists of a symbolic link to 
-\emph on 
-port/makedefs.sh
-\emph default 
-, which contains the configuration information required to build the for
- the target port system.
- The paths to the various useful utilities are assigned to shell variables.
- If functions need to be supplied for other build scripts, they also should
- be defined here.
- This file is sourced (included) by all other build scripts.
- They all should use the variables supplied by this file when accessing
- the cross-compile or local utilities.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/make.sh
-\emph default 
- allows to fully compile the kernel to result in a kernel image.
- Requires the target port name to be specified, as it also sets up required
- symbolic links.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-src/clean.sh
-\emph default 
- cleans the source tree, that is, deletes all files which may have been
- created by the build process.
-\layout List
-\labelwidthstring 00.00.0000
-
-*
-\emph on 
-/make.sh
-\emph default 
- The various sections described below will need such a script which should
- perform the necessary steps to compile the section.
- These 
-\emph on 
-source
-\emph default 
- src/
-\emph on 
-makedefs.sh
-\emph default 
- to know which commands to invoke and access useful 
-\emph on 
-/bin/sh
-\emph default 
- macros..
-\layout List
-\labelwidthstring 00.00.0000
-
-*
-\emph on 
-/clean.sh
-\emph default 
- The sections also need such a script which is expected to delete all files
- which the 
-\emph on 
-make.sh
-\emph default 
- script counterpart creates.
- These 
-\emph on 
-source
-\emph default 
-\emph on 
-src/generic_makedefs.sh
-\emph default 
-.
-\layout Paragraph
-
-Cleaning the whole source tree
-\layout Standard
-
-The 
-\emph on 
-src/clean.sh
-\emph default 
- script ensures to clean the whole source tree by calling the 
-\emph on 
-clean.sh
-\emph default 
- script for each section, including all ports and processors.
- The invoker is expected to be in the 
-\emph on 
-src/
-\emph default 
- directory.
-\layout Paragraph
-
-Building the system
-\layout Standard
-
-The 
-\emph on 
-src/make.sh
-\emph default 
- script builds the entire system.
- The main steps performed to compile the system are described as follows,
- in order.
-\layout Subsubsection
-
-Preliminary building process setup
-\layout Standard
-
-The 
-\emph on 
-src/processor,
-\emph default 
-\emph on 
-src/port
-\emph default 
- and 
-\emph on 
-src/makedefs.sh
-\emph default 
- symbolic links should point to their corresponding 
-\emph on 
-src/processors/<directory>
-\emph default 
- and 
-\emph on 
-src/ports/<directory>
-\emph default 
- and 
-\emph on 
-src/ports/<directory>/makedefs.sh
-\emph default 
-.
- These are setup depending on the target system for which Xisop is being
- built.
- Each of these (port and processor sections) supplies a 
-\emph on 
-support.h
-\emph default 
- headerfile which should be sufficient for the rest of the kernel code to
- access the functionality of the hardware specific code they provide.
- Moreover, each of them will after building provide 
-\emph on 
-ar
-\emph default 
- archives (
-\emph on 
-.a
-\emph default 
- files) into their respective 
-\emph on 
-ar/
-\emph default 
- directory, resulting from their various object files, which will be sufficient
- to link with the rest of the kernel code to achieve the end result.
- The 
-\emph on 
-src/make.sh
-\emph default 
- script creates these symbolic links when supplied with a valid 
-\emph on 
-target
-\emph default 
- (using the 
-\emph on 
--t
-\emph default 
- parameter).
-\layout Standard
-
-
-\emph on 
-src/make.sh
-\emph default 
- also ensures to set the 
-\emph on 
-$SRCDIR
-\emph default 
- environment variable to the absolute path to the current directory (
-\emph on 
-src/
-\emph default 
-), which should be used by other build scripts when compiling modules so
- that 
-\emph on 
-#include
-\emph default 
- directives in the source can locate the file using 
-\emph on 
--I
-\emph default 
- parameter, etc.
-\layout Subsubsection
-
-Building the processor-specific support code
-\layout Standard
-
-Control is delegated to 
-\emph on 
-src/processor
-\emph default 
-/
-\emph on 
-make.sh
-\emph default 
-.
- This is expected to assemble and compile the various sections it comports
- to binary objects independently (
-\emph on 
-.o
-\emph default 
-) using 
-\emph on 
--c
-\emph default 
- parameter to 
-\emph on 
-gcc
-\emph default 
- command, and to then archive them as 
-\emph on 
-ar
-\emph default 
- archives into the 
-\emph on 
-src/processor/ar
-\emph default 
- directory using the 
-\emph on 
-ar
-\emph default 
- and 
-\emph on 
-ranlib
-\emph default 
- commands.
- This final object will be linked with the kernel code by another section
- of the build process.
- It is to be noted that it will be linked before the general common machine-inde
-pendent kernel library, so that it is possible to provide processor-specific
- replacements to standard low-level functions, such as 
-\emph on 
-memcpy()
-\emph default 
-, 
-\emph on 
-memset()
-\emph default 
-, etc.
- These could however be overriden by the port-specific support code.
- When control is given to 
-\emph on 
-make.sh
-\emph default 
- of this section, the current directory will have been changed as well so
- that it is safe to access the section files relatively to the current (section)
- directory.
-\layout Subsubsection
-
-Building the port-specific support code
-\layout Standard
-
-Control is given to 
-\emph on 
-src/port/make.sh
-\emph default 
- to compile this section, and very similarly to the processor-specific section,
- the goal is to generate one or more 
-\emph on 
-ar
-\emph default 
- archive in the 
-\emph on 
-src/port/ar
-\emph default 
- directory.
-\emph on 
-src/port/support.h
-\emph default 
- will also contain all necessary information for the rest of the kernel
- code to use the port-specific support.
- This code will be linked with the global kernel before s
-\emph on 
-rc/processor/ar/*.a
-\emph default 
-, which means that it is possible to provide port-specific standard functions
- overriding the processor-specific ones, as well as kernel machine-independent
- common ones.
- This could allow for instance to provide 
-\emph on 
-memcpy()
-\emph default 
- and 
-\emph on 
-memset()
-\emph default 
- functions using specialized data moving hardware such as blitters, etc.
- It is however recommended that libraries be built in a way to not force
- the whole library to be included into the final kernel if only a few of
- the functions were necessary.
- To do this, a library could consists of a directory, with all functions
- isolated in their own 
-\emph on 
-.c
-\emph default 
- file.
- The 
-\emph on 
-ar
-\emph default 
- archive then results in a bunch of very small 
-\emph on 
-.o
-\emph default 
- files which will be ignored by the linker when unrequired.
- It is important to also run 
-\emph on 
-ranlib
-\emph default 
- on the 
-\emph on 
-ar
-\emph default 
- archive.
-\layout Standard
-
-
-\emph on 
-XXX
-\emph default 
-\emph on 
-Hmm I should find a nice way to define the resident libraries, devices and
- handlers, both common and port-specific ones.
- Also, which tasks should be initially started, etc.
- Actually, resident devices and handlers, being tasks, would just need to
- be included in the tasks to start, I guess...
-\layout Standard
-
-
-\emph on 
-XXX This next paragraph is currently invalid.
-\layout Standard
-
-The 
-\emph on 
-ar/*.a
-\emph default 
- result should also include 
-\emph on 
-_init_libraries()
-\emph default 
-, 
-\emph on 
-_init_devices()
-\emph default 
- and 
-\emph on 
-_init_handlers()
-\emph default 
- functions, which should as required attach the wanted shared libraries,
- devices and handlers in the kernel by calling their init function.
- These also should initialize machine-independent ones.
- If there are port-dependent ones, their code should be located into the
-\emph on 
-library/
-\emph default 
-, 
-\emph on 
-device/
-\emph default 
- and 
-\emph on 
-handler/
-\emph default 
- directories in 
-\emph on 
-src/port/
-\emph default 
-.
-\layout Subsubsection
-
-Building the machine-independent main Xisop code
-\layout Standard
-
-The 
-\emph on 
-src/common/kernlib/
-\emph default 
- directory comports a directory for each internal kernel library, which
- each contain functions isolated into a single file each.
- These are built separately as object modules, and are archived using 
-\emph on 
-ar
-\emph default 
- and 
-\emph on 
-ranlib
-\emph default 
- into 
-\emph on 
-src/common/kernlib/ar 
-\emph default 
-directory.
- The reason for this is that it allows the resulting kernel image to be
- smaller when not all of the functions of a particular library are used.
- If all string functions were located into the same 
-\emph on 
-string.c
-\emph default 
- file for instance, all of the string functions would automatically be linked
- within the result even if only two string functions were actually used,
- for instance.
-\layout Standard
-
-The 
-\emph on 
-src/common/kernel/
-\emph default 
- and 
-\emph on 
-src/common/kernlib/
-\emph default 
- sections containing only portable C code are compiled, and their modules
- archived with 
-\emph on 
-ar
-\emph default 
- and 
-\emph on 
-ranlib
-\emph default 
-, to 
-\emph on 
-src/common/kernel/ar/*.a
-\emph default 
- and 
-\emph on 
-src/common/kernlib/ar/*.a
-\emph default 
- files.
- At current time, 
-\emph on 
-src/common/library/
-\emph default 
-, 
-\emph on 
-src/common/device/
-\emph default 
- and 
-\emph on 
-src/common/handler/
-\emph default 
- sections are all compiled and archived together as 
-\emph on 
-src/common/ar/*.a
-\emph default 
-.
-\emph on 
-XXX This last statement is false as nothing is done for libraries, devices
- and handlers at current time..
-\layout Subsubsection
-
-Linking the final kernel
-\layout Standard
-
-
-\emph on 
-src/common/kernel/kernel
-\emph default 
-.
-\emph on 
-a
-\emph default 
-, 
-\emph on 
-src/port/support.
-\emph default 
-a, 
-\emph on 
-src/processor/support.a
-\emph default 
-, 
-\emph on 
-src/common/kernlib/kernlib.a
-\emph default 
- and 
-\emph on 
-src/common/shared.a
-\emph default 
- are linked together, in that order, into the ELF relocatable 
-\emph on 
-src/xisop.o
-\emph default 
- file (using 
-\emph on 
--r
-\emph default 
- option to ld).
- This allows processor-specific libraries to replace 
-\emph on 
-common/kernlib
-\emph default 
- functions, and port-specific ones to override both processor-specific and
- common ones.
-\layout Subsubsection
-
-Linking the final kernel and building the bootable Xisop result
-\layout Standard
-
-After building both the machine dependent and independent sections described
- above, the control is then left to 
-\emph on 
-src/port/boot/make.sh
-\emph default 
-, after changing to the 
-\emph on 
-src/port/boot directory
-\emph default 
-.
- The role of this final script is to complete the linking and building process.
- Here is what currently happens:
-\layout Standard
-
-As a general rule, image_script.ld file in that directory comports the necessary
- information to statically link monolithically the whole kernel as a binary
- image.
- Here is an excerpt of what 
-\emph on 
-src/ports/amiga/boot/make.sh
-\emph default 
- does:
-\layout Itemize
-
-show $C_COMPC -I$SRCDIR init.c
-\layout Itemize
-
-A=`$L_LS ../../../common/kernel/ar/*.a ../ar/*.a ../../../processor/ar/*.a ../..
- /../common/kernlib/ar/*.a`
-\layout Itemize
-
-show $C_LD -nostdlib -e _start -Ttext 0x005f8000 -o image.o init.o $A
-\layout Itemize
-
-show $C_LD -T image_script.ld -nostdlib -o image.bin init.o $A
-\layout Itemize
-
-...
-\layout Standard
-
-The first operation compiles it's initialization code, which provides the
-\emph on 
-_start
-\emph default 
- entrypoint, which eventually calls Xisop 
-\emph on 
-main()
-\emph default 
-.
- Then is compiled a list of the various 
-\emph on 
-ar
-\emph default 
- archives which should be linked.
- The order of these archives is important, as it permits the processor-specific
- code to override the common code, and the port-specific code to override
- the processor specific and common code.
-\layout Standard
-
-Then follows the linking process, which is done two time.
- The first instance creates 
-\emph on 
-image.o
-\emph default 
- which can then be viewed and disassembled using the 
-\emph on 
-objdump
-\emph default 
- utility.
- This is mostly used for debugging so that at runtime in the emulator it
- is possible to stop the emulation process and fall into the debugger, which
- then discloses the current executing address.
- That same address in image.o disassembly should match, and this is where
- it can be handy.
-\layout Standard
-
-The second linking command creates the binary Xisop kernel image using the
-\emph on 
-image_script.ld
-\emph default 
- linker script, to result in 
-\emph on 
-image.bin
-\emph default 
-.
- This is the actual image, which expects to be loaded into memory at the
- address 0x005f8000, and jumped to.
- (See the 
-\emph on 
-image_script.ld
-\emph default 
- and 
-\emph on 
-make.sh
-\emph default 
- scripts for more information).
-\layout Standard
-
-The script then proceeds to compile the disk boot loader (floppy in this
- case), which is located into the 
-\emph on 
-bootf/
-\emph default 
- directory.
- It then compiles the tools which are needed to assemble the result and
- fix the bootblock checksum using the the local compiler (not the cross
- compiler, although the same compiler could be used for both local and cross,
- if the target and the build system are the same).
- It finally uses those tools to create the final xisop.adf floppy image,
- and advertizes the location of this file to the user.
-\layout Standard
-
-Those last steps are very port-specific and are best done by someone with
- a good amount of experience for the particular port to ensure that it works
- right.
- It is important to advertize the location of the final result to the user
- at the very end.
-\layout Section
-\pagebreak_top 
-Hardware specific development notes
-\layout Standard
-
-This chapter describes which hardware specific sections are required to
- support Xisop.
- They in fact provide the low-level glue which all the machine-independent
- common code replies on.
- As such, they should be small, effective, and as efficient and stable as
- possible.
- They should be well tested before releasing an official new Xisop port.
-\layout Standard
-
-To aid in having a well organized source tree, and to prevent code duplication,
- hence enhancing stability with time, the processor-specific and port-specific
- sections have been separated into two.
- Several ports may then take advantage of the same processor-specific code,
- such as atomic locking primitives, which are known to work well, which
- helps alot to speed up development.
-\layout Subsection
-
-Microprocessor specific notes
-\layout Subsubsection
-
-Required backend functions and support
-\layout Standard
-
-Each processor is different but it is great to abstract most CPU-specific
- functions into a standard set.
- The headerfile which will be invoked by the common machine-independent
- parts of the kernel to acquire support for the hardware specific functions
- is 
-\emph on 
-processor/support.h
-\emph default 
-, where 
-\emph on 
-processor
-\emph default 
- will consist of a symbolic link to the actual 
-\emph on 
-processor
-\emph default 
- directory in use in the 
-\emph on 
-processors
-\emph default 
- directory.
- Although the general organization of the processor specific code is implementat
-ion dependent, it is important that 
-\emph on 
-support.h
-\emph default 
- loads support for all necessary functions and data types which are processor-sp
-ecific, and that 
-\emph on 
-ar/*.a
-\emph default 
- be the only necessary modules to link with the rest of the kernel.
-\layout Standard
-
-It is allowed if desired to also supply processor specific functions to
- replace some of the common machine-independent ones, which may be desired
- for speed at occasions.
- When this is done, the functions should behave identically as expected,
- should bear the same names, and no prototypes should be provided for them
- in 
-\emph on 
-support.h
-\emph default 
-.
- The processor-specific code will be linked to the final kernel before the
- common libraries and those functions will replace the machine-independent
- ones then.
- These functions could be for instance: 
-\emph on 
-memcmp()
-\emph default 
-,
-\emph on 
- memcpy()
-\emph default 
-, 
-\emph on 
-memset()
-\emph default 
-, etc.
-\layout Standard
-
-Here are the various recommended functions which each CPU should support,
- and make public to the rest of the kernel, at a minimum:
-\layout Paragraph
-
-Context manipulation
-\layout Standard
-
-The 
-\emph on 
-_ctx_t
-\emph default 
- structure should be defined by the CPU-specific support headerfile and
- should be used as an abstract type representing all required information
- to save or restore a context, thus all registers, status register (SR),
- stack pointer (SP), and program counter (PC).
- The load and save context code sections are generally port-specific are
- called from an interrupt, and as needed some care will be taken to save
- the user stack pointer (USP) rather than the supervisor stack pointer (SSP),
- as their purpose consist of task switching.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_ctx_init(_ctx_t\SpecialChar ~
-*context,\SpecialChar ~
-u_int32_t\SpecialChar ~
-*stack,\SpecialChar ~
-size_t\SpecialChar ~
-stacksize,\SpecialChar ~
-void\SpecialChar ~
-*start)
-\emph default 
- Allows to create a new CPU context.
- On some systems the stack grows downwards while upwards on others.
- For this reason, the 
-\emph on 
-stacksize
-\emph default 
- argument is used which permits to set the stack pointer as required, because
-\emph on 
-stack
-\emph default 
- should be a pointer to the top of the stack.
-\emph on 
-start
-\emph default 
- is a function pointer to the code to execute (stack startup address).
- Usually, SP and PC are set accordingly in 
-\emph on 
-context
-\emph default 
-, SR set to the current one, and other registers zeroed.
- In some cases it may be good to also ensure to turn off the supervisor
- bit from SR in the context, because user tasks are expected to run in userstate
- processor mode.
-\layout Paragraph
-
-Simple lock support
-\layout Standard
-
-
-\emph on 
-_lock_t
-\emph default 
- should also be defined for abstraction, and help to perform various synchroniza
-tion tasks.
- These need not be symetric multiprocessor (SMP) safe, but they should at
- least be atomic for the current processor.
- Atomic in the sense that test-and-set must be performed at once to acquire
- a lock.
- If a processor does not allow to make this atomic, it is possible to provide
- these by the port-specific code, in which case it could disable interrupts
- (at least the scheduler interrupt) before performing it's tasks, so that
- operations seem atomic in a multitasking environment.
- These lock primitives should not be nestled or recursive, they are intended
- for exclusive access.
-\layout Standard
-
-In any case, all following lock primitives should be callable by normal
- user tasks, which means that when required a trap can be used internally
- to swich to supervisor mode if the processor requires to perform privileged
- instructions to achieve the expected atomic behavior, both for 
-\emph on 
-_lock_t
-\emph default 
- and 
-\emph on 
-_rlock_t
-\emph default 
- primitives.
- Fortunately, they can usually be implemented properly using normal instructions.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_lock_init(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- Permits to initialize a 
-\emph on 
-_lock_t
-\emph default 
- entity as required for future operations on this 
-\emph on 
-lock
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_lock_acquire(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- Allows to obtain exclusive access on the supplied 
-\emph on 
-lock
-\emph default 
-, or wait looping indefinitely until the lock could be obtained, in order
- to obtain it as fast as possible.
- It is important that this operation be atomic so that in the event of scheduled
- context switching race conditions do not occur.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_lock_release(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- Should free the specified 
-\emph on 
-lock
-\emph default 
-, which will enable any other requester to acquire the lock to obtain it.
- This operation also should be atomic.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-_lock_try(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- Attempts to obtain exclusive access to 
-\emph on 
-lock
-\emph default 
-, returning TRUE/1 if it could obtain it immediately, or FALSE/0 if the
- lock is already being held, in which case it also returns immediately.
- It is important that this be implemented atomically, in a single test-and-set
- instruction.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-bool\SpecialChar ~
-_lock_available(_lock_t\SpecialChar ~
-*lock)
-\emph default 
- Verifies if 
-\emph on 
-lock
-\emph default 
- is available.
- This is not to be used to implement 
-\emph on 
-_lock_try()
-\emph default 
-, it is used in situations where we only want to make sure that no lockers
- currently own the lock, but that we still do not want to obtain it ourselves.
- An example of this is where a lock is used as an ON/OFF switch, which can
- be implemented using this mechanism, without disabling the event which
- needs to access a resource, which may serve other functions but will skip
- executing the critical code if the scheduler lock is held.
- This is usually best implemented using recursive 
-\emph on 
-_rlock_t
-\emph default 
- however, which will be described below.
-\layout Standard
-
-The following locking primitives are different in that a lock may be locked
- by any number of lockers, but has to be unlocked the same number of times
- for the lock to become free again.
- These are called recursive locks.
- A useful example consists of the scheduler which wants to ensure that no
- task disabled the scheduler temporarily before performing a context switch.
- It then evaluates the lock using 
-\emph on 
-_rlock_available()
-\emph default 
-, or 
-\emph on 
-_rlock_try()
-\emph default 
- if it needs to prevent recursion, and only performs the switch if it is
- (and hence the lock counter equals to 0, or 1).
- It is recommended that the 
-\emph on 
-_rlock_t
-\emph default 
- type consist of an 
-\emph on 
-int32_t
-\emph default 
- (signed), but the processor-specific code is left to define it differently
- if need be.
-\layout Standard
-
-Although for several architectures C code can also be used to implement
- these, it is a good idea to implement them in assembly because there is
- no guarantee that the compiler will always use atomic increase and decrease
- operations (GCC 2.95.3 at least seems to not always do so for m68k with C
- macros, it often loads the value from the lock counter, increase it during
- other processing and posts back the new value over the counter, instead
- of always generating an atomic increment instruction which m68k is well
- capable of).
- Moreover, for some other architectures the use of an internal 
-\emph on 
-_lock_t
-\emph default 
- or 
-\emph on 
-_splhigh()
-\emph default 
- may be required to implement these properly, and if there are privileged
- instructions required to implement these, a trap may be needed.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_rlock_init(_rlock_t\SpecialChar ~
-*rlock)
-\emph default 
- Initializes 
-\emph on 
-rlock
-\emph default 
- to 0.
- This normally is rarely done except at system initialization, or lock creation.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_rlock_acquire(_rlock_t\SpecialChar ~
-*rlock)
-\emph default 
- Atomically increases the 
-\emph on 
-rlock
-\emph default 
- counter by one.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_rlock_release(_rlock_t\SpecialChar ~
-*rlock)
-\emph default 
- Atomically decreases the 
-\emph on 
-rlock
-\emph default 
- counter by one.
- There is no need to perform any check against 0 in this function.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_rlock_try(_rlock_t\SpecialChar ~
-*rlock)
-\emph default 
- Permits to atomically increase the 
-\emph on 
-rlock
-\emph default 
- counter by one, and returns TRUE if the caller consists of the only locker
- (in which case the lock counter should now be 1).
- If the counter is higher, it means that more than one locker exists and
- the function is then expected to decrease the counter atomically again,
- and return FALSE.
- This allows exclusive access to a recursive lock.
- This function is both used by the scheduler and public interrupt facility
- systems.
- Because they want to make sure that noone holds the lock when they execute
- their critical tasks, and that they also need to lock it to prevent potential
- self-recursion, this call is a great facility to use.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_rlock_available(_rlock_t\SpecialChar ~
-*rlock)
-\emph default 
- Returns TRUE if the 
-\emph on 
-rlock
-\emph default 
- counter equals to 0, or FALSE otherwise (in which case there at least remains
- one current locker).
- This function is provided for callers which do not need to prevent possible
- recursion, but only need to make sure that the lock is currently free.
- Following 
-\emph on 
-_rlock_available()
-\emph default 
- with 
-\emph on 
-_rlock_acquire()
-\emph default 
- is not safe, and 
-\emph on 
-_rlock_try()
-\emph default 
- should be used instead when this is desired.
-\layout Paragraph
-
-Byte order conversion support
-\layout Standard
-
-The processor-specific code needs to #define 
-\emph on 
-_ARCH_BIG_ENDIAN
-\emph default 
- or 
-\emph on 
-_ARCH_LITTLE_ENDIAN
-\emph default 
- in their 
-\emph on 
-support.h
-\emph default 
- depending on their native byte order.
- These will be used at a higher level in the libraries for the endian-conversion
- functions between network (big endian) and host order (big or little endian).
- These are most useful when saving a binary file format which needs to be
- loadable by another processor of another endian order as well as in the
- implementation of networking based Remote Procedure Calls, etc.
- Moreover, the two following functions should be provided:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-u_int16_t\SpecialChar ~
-_bswap16(u_int16_t)
-\emph default 
- Swaps the order of the two bytes held in the supplied 16-bit word and returns
- the result.
- For instance, 0x1234 becomes 0x3412.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-u_int32_t\SpecialChar ~
-_bswap32(u_int32_t)
-\emph default 
- Reverses the order of the four bytes held in the supplied 32-bit word and
- returns the result.
- For instance, 0x12345678 becomes 0x78563412.
-\layout Paragraph
-
-String library optimizations support
-\layout Standard
-
-Note that the following are not necessary to consider if a specially optimized
- library functions for string and memory are implemented in assembly for
- the architecture.
-\layout Standard
-
-Every other architecture should 
-\emph on 
-#define
-\emph default 
- the architecture-specific 
-\emph on 
-__ARCH_INT_BITS
-\emph default 
- macro, which should be set to the native word size used by the particular
- processor for int, using the compiler.
- This should be expressed in bits, not in bytes.
- The most common value is 32, but it can vary.
-\layout Standard
-
-It is also important to 
-\emph on 
-#define
-\emph default 
- the 
-\emph on 
-_ARCH_LOWCACHE
-\emph default 
- macro (with no value), if it is beleived that loop unrolling is of no benefit.
- This can be the case on architectures with very low instruction caches,
- or ones which are using none.
- If loop unrolling is wanted, this should not be defined.
-\layout Standard
-
-The 
-\emph on 
-_ARCH_USEINDEXING
-\emph default 
- macro also should be 
-\emph on 
-#defined
-\emph default 
- with no value if it is beleived that the compiler generates better code
- for this particular processor when using indexed instructions rather than
- many post-increment/pre-decrement pointer based instructions.
- For instance, the i386 processor has no such special support, and using
- indexing can generate better code using GCC2.
- For m68k, it is usually better not to use indexing.
- Note that this is only taken in consideration if 
-\emph on 
-_ARCH_LOWCACHE
-\emph default 
- is not defined, as it only affects loop unrolling of the C string and memory
- library.
-\layout Standard
-
-These definitions are expected to be found in the 
-\emph on 
-support.h
-\emph default 
- file for every particular processor.
-\layout Paragraph
-
-CPU-saving
-\layout Standard
-
-On CPUs which support this, it is very useful to not hug the processor constantl
-y in a loop where the only event that is awaited for consists of an interrupt.
- On microprocessors which do not provide such a feature, it is safe to just
- make this function do nothing.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_idle(void)
-\emph default 
- Suspends execution of instructions by the current processor until the next
- interrupt, trap or exception occurs.
-\layout Paragraph
-
-Interrupt level control
-\layout Standard
-
-Most microprocessors support several interrupt levels, where the higher
- the level the better precedence of execution over others.
- Manipulating the interrupt priority level (IPL) using Set Priority Level
- functions becomes useful for critical code sections which need to disable
- all interrupts at the specified level and under.
- Although port-specific code attempts to provide it's own finer grained
- interrupt control code when considered required, these should be available.
- The 
-\emph on 
-_ipl_t
-\emph default 
- type itself is left to be defined with 
-\emph on 
-typedef
-\emph default 
- by the processor-specific code to the best variable type to hold the processor
- IPL state.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_ipl_t\SpecialChar ~
-_spl
-\emph default 
-n
-\emph on 
-(void)
-\emph default 
- Immediately sets the current priority level to the one specified by 
-\emph on 
-n
-\emph default 
-.
- Thus, functions such as 
-\emph on 
-_spl0()
-\emph default 
-, 
-\emph on 
-_spl1()
-\emph default 
-, 
-\emph on 
-_spl2()
-\emph default 
-, etc should be provided, for each interrupt level.
-\emph on 
-_spl0()
-\emph default 
- should enable all interrupt levels to occur.
- The returned value serves to eventually restore the previous interrupt
- level using 
-\emph on 
-_splx()
-\emph default 
-, and is an abstract type defined by the processor-specific code.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_ipl_t\SpecialChar ~
-_splhigh(void)
-\emph default 
- Usually a macro to the highest 
-\emph on 
-_spl
-\emph default 
-n
-\emph on 
-()
-\emph default 
- function, it disables all interrupts by setting the highest priority level,
- thus masking all interrupts.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_splx(_ipl_t\SpecialChar ~
-state)
-\emph default 
- Permits to restore the previous interrupt priority level which was active
- before a call to an 
-\emph on 
-_spl
-\emph default 
-*
-\emph on 
-()
-\emph default 
- function was made, using the state value which was supplied by them.
-\layout Subsubsection
-
-m68k
-\layout Standard
-
-The Motorola MC68000L8 and MC68000L10 processors were the first to run Xisop.
- No support for MMU is present, such memory management units usually come
- on other external circuits for this processor, and there are various types.
- As Xisop does not need MMU, those processors were an ideal target.
- Although internally built as 16-bit processors, these processors behave
- as 32-bit ones from the programming point of view.
- It is also expected to run the same (or with minor modifications to disable
- their MMU) on the other processors of the 680x0 family, which are fully
- 32-bit.
- The assembly code observes the following rules to properly work with GCC
- compiled C modules:
-\layout Itemize
-
-Stack pointer consists of A7/SP and frame pointer of A6/FP.
- In supervisor mode, the user stack pointer consists of USP and specialized
- instructions need to be used to access and manipulate it.
-\layout Itemize
-
-Registers A0 and D0 serve the special purpose of return code for functions.
- Where the C code expects A0 or D0 to be used depends on the function prototype
- as seen from C.
- Functions expected to return a pointer should do so in A0, and D0 is used
- for other integer values.
- Assembly functions expected to be called from C must have a C function
- prototype defined in a headerfile which the C code must include.
-\layout Itemize
-
-Assembly functions save all the registers they modify, and restore them
- before returning.
- As such, functions returning nothing (void) are expected to never return
- with a different register state.
- However, this is not always true of GCC generated code.
- Of course, the D0 register in the case of integer returning functions,
- and A0 for pointer returning ones should as expected modify the corresponding
- register as well.
- Registers to be saved are pushed on the stack, which grows upwards.
-\layout Itemize
-
-Because there are various registers which GCC generated code modifies without
- always saving, exception handlers save all general purpose registers A0-A6
- and D0-D7 registers, and restore them before returning with RTE.
- It was a false assumption to previously only backup A0 and D0 which are
- used as function return codes, and many problems occurred back then with
- this attempt.
-\layout Itemize
-
-When an assembly function calls a C function, it needs to push the arguments
- in the stack, growing upwards, in reverse order, before calling it.
- After the C function returned, the stack pointer should be updated by additioni
-ng the number of bytes that were pushed.
- In the case where 16-bit or 8-bit values are passed as arguments, GCC still
- expects a stack entry of 32-bit size.
-\layout Itemize
-
-An assembly function expected to be called from C must obtain the arguments
- (if any) from the stack.
- These are ordered growing downwards, as they were inserted in reverse order
- in the stack, growing upwards.
- Obviously, when registers are temporarily saved on the stack to preserve
- their state and restore them before returning, the offset at which these
- parameters are found on the stack changes, and the code has to account
- for this.
-\layout Itemize
-
-The 
-\emph on 
-_ctx_t
-\emph default 
- manipulation functions had to be implemented as follows: 
-\emph on 
-_ctx_init()
-\emph default 
- can be called from usermode and only creates a context with zero registers,
- etc.
- However, 
-\emph on 
-_yield()
-\emph default 
- had to be implemented using a trap to execute in supervisor mode, and the
- scheduler preemptive interrupt also executes in supervisor mode.
- Both save the current context to 
-\emph on 
-root->curctx
-\emph default 
-, call 
-\emph on 
-schedule()
-\emph default 
- and load back the context from
-\emph on 
- root->curctx
-\emph default 
-, as expected.
- They need to use privileged instructions to change SR (status register)
- and USP (user stack pointer), because SR/A7 becomes the SSP (supervisor
- stack pointer) when in supervisor mode.
- To make sure to respect the PC (program counter) address of the contexts,
- they are manipulated on the supervisor stack (SSP), where the m68k saves
- them when jumping to the exception handler.
- As such, RTE (return from exception) automatically jumps where it should
- for the current context.
- The offset to the SR 16-bit register is usually %sp@ and the one for PC
- 32-bit one in %sp@(2) when initially intering the trap or interrupt exception.
- This offset has to be recalculated as registers are being saved on the
- stack, of course.
-\layout Standard
-
-Other m68k specific notes about aspects which had to be taken in consideration:
-\layout Itemize
-
-At kernel initialization, room for the supervisor stack pointer needs to
- be setup, and the Supervisor Stack Pointer (SSP/A7) should be set properly.
- To do this it is necessary to go in supervisor mode, and then set the A7
- register to the right address.
- The way this must be done depends on the architecture.
- Because at bootup ROM code may have taken control already and one must
- use it's own facilities to obtain supervisor privileges.
-\layout Itemize
-
-Dropping to user state from supervisor state to call Xisop 
-\emph on 
-main()
-\emph default 
- is rather simple.
- 1024 bytes are taken from the current SSP (A7), and assigned to the USP.
- The supervisor bit in SR is then unset, and a jump to 
-\emph on 
-main()
-\emph default 
- is made.
- The function is very tiny and only ensures to launch the various initial
- tasks, then waits forever in a loop using 
-\emph on 
-_idle()
-\emph default 
- calls via 
-\emph on 
-sys_idle()
-\emph default 
-.
- It corresponds to the 
-\emph on 
-_scontext
-\emph default 
-\emph on 
-_ctx_t
-\emph default 
- in 
-\emph on 
-root->curctx
-\emph default 
- when no tasks are on the ready queue.
- Such a small stack buffer is then safe.
-\layout Itemize
-
-Using GCC 2.95.3, -O2 and -fomit-frame-pointer compilation directives seem
- to generate both well optimized and small m68k code.
- I however noted that using -fno-function-cse was also required with -O2,
- without which the resulting code crashed.
- -m68000 was used to generate true MC68000 code (no support for 020+ specific
- instructions which wouldn't run on a plain 68000).
-\layout Itemize
-
-Although m68k is very good to produce position-independent code, the default
- output GCC produces still comports instructions using direct addressing,
- except when -fpic is used, in which case additional symbols, with a .got
- table need to also be in the code, even if m68k generally doesn't require
- these for position-independent code (it has all the relative addressing
- instructions required for large memory model).
- As the only solution I found to properly relocate the code upon loading
- would be to write an ELF or a.out loader, which isn't done yet, the kernel
- code is loaded at a specific location, defined before compilation.
- A GCC ld BFD backend will need to be written, or an ELF loader, to allow
- to relocate the kernel, as well as file executable binaries.
-\layout Itemize
-
-The 
-\emph on 
-_spl
-\emph default 
-n
-\emph on 
-()
-\emph default 
- and 
-\emph on 
-_splhigh()
-\emph default 
- functions were implemented as macros, calling the assembly 
-\emph on 
-_spl()
-\emph default 
- function which takes a 16-bit argument (the new SR to apply).
-\emph on 
-_splx()
-\emph default 
- assembly functions restores the previous SR.
- As SR is 16-bit, the 
-\emph on 
-_ipl_t
-\emph default 
- type was defined as an 
-\emph on 
-u_int16_t
-\emph default 
- internally.
- This allowed to generate very compact code for the eight interrupt priority
- level control functions which m68k required.
-\layout Itemize
-
-The 
-\emph on 
-_lock_
-\emph default 
-*
-\emph on 
-()
-\emph default 
- functions were implemented using the TAS instruction for atomicity, and
- the 
-\emph on 
-_lock_t
-\emph default 
- data type was internally defined as an 
-\emph on 
-u_int8_t
-\emph default 
-.
-\layout Itemize
-
-The 
-\emph on 
-_rlock
-\emph default 
-*
-\emph on 
-()
-\emph default 
- functions could be implemented without the use of an internal 
-\emph on 
-_lock_t
-\emph default 
- to guarrantee atomicity, because the m68k processor is capable of addition
- and substraction on a 32-bit value in a single instruction.
- An 
-\emph on 
-_rlock_t
-\emph default 
- consists of a 
-\emph on 
-int32_t
-\emph default 
- for this architecture.
-\layout Itemize
-
-Before the port-specific code calls Xisop 
-\emph on 
-main()
-\emph default 
-, it is necessary to switch back to user processor mode.
- The 
-\emph on 
-_usermode()
-\emph default 
- function was implemented for this and added to the m68k set of processor-specif
-ic functions, which allows to create a 1024 bytes user stack from the current
- supervisor stack, switches to usermode, and jumps to the specified function.
-\layout Subsection
-
-Port specific notes
-\layout Subsubsection
-
-Required backend and support functions
-\layout Standard
-
-Each architecture needs a specific initialization section, such as setting
- up exceptions, interrupts and memory.
- Although this can also be CPU-specific, the various architectures using
- the same processor would most likely still need these to be different.
- They are thus considered as port-specific low-level backend support.
- Similarly to the processor-specific support code, 
-\emph on 
-support.h
-\emph default 
- and 
-\emph on 
-ar/*.a
-\emph default 
- are the main targets that should be provided to allow the rest of the kernel
- to use it, as it will include 
-\emph on 
-port/support.h
-\emph default 
- and will link in 
-\emph on 
-port/ar/
-\emph default 
-*.
-\emph on 
-a
-\emph default 
-, where 
-\emph on 
-port
-\emph default 
- consists of a symbolic link to the actual 
-\emph on 
-ports/<name>
-\emph default 
- directory.
-\layout Standard
-
-It is allowed if desired to also supply port specific functions to replace
- some of the common machine-independent ones, which may be desired for speed
- at occasions.
- When this is done, the functions should behave identically as expected,
- should bear the same names, and no prototypes should be provided for them
- in 
-\emph on 
-support.h
-\emph default 
-.
- The port-specific 
-\emph on 
-ar/*.a 
-\emph default 
-modules will be linked before the processor-specific and Xisop common libraries
- and those functions will replace them if they are supplied.
- These functions could be for instance: 
-\emph on 
-memcmp()
-\emph default 
-,
-\emph on 
- memcpy()
-\emph default 
-, 
-\emph on 
-memset()
-\emph default 
-, etc.
-\layout Standard
-
-After the kernel was built, using both common, processor and port code,
- control is left again to the port specific code which should handle boot
- support; This can be creating a floppy image, etc.
- See the section on the building process for more information.
-\layout Standard
-
-It is important that the port-specific code provides the 
-\emph on 
-_start
-\emph default 
- entry point.
- This code should then set the processor in supervisor mode where required,
- setup the supervisor mode stack pointer, disable interrupts and perform
- initialization of the various systems described below.
- Afterwards, it should switch back to userstate processor mode, and leave
- control to the Xisop 
-\emph on 
-main()
-\emph default 
- function, which will not return.
- That 
-\emph on 
-_start
-\emph default 
- entry point is where the boot kernel loader needs to jump to.
-\layout Paragraph
-
-Memory initialization and requirements
-\layout Standard
-
-The port-specific 
-\emph on 
-support.h
-\emph default 
- should define C enumerators (enum) and definitions (#define) for the machine-in
-dependent Xisop memory code.
- It is recommended to also read the section on Xisop memory management for
- more information.
- The port-specific requirements are explained as follows:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-#define\SpecialChar ~
-_PAGE_SIZE\SpecialChar ~
-<value>
-\emph default 
- The memory management system needs to know the amount of bytes in which
- to split pages.
- On operating systems which support Memory Management Units (MMU), this
- is required to match the page size which the hardware requires.
- In the case of Xisop, it is safe to use any reasonable multiple of 16 bytes
- here.
- A common 
-\emph on 
-_PAGE_SIZE
-\emph default 
- is 4096 bytes.
- On systems with very low memory it may be useful to use 1024, or even 256.
- This value is used by the page memory allocation primitives.
-\layout Standard
-
-The 
-\emph on 
-mpool_t
-\emph default 
-, a multi-purpose memory pool which allows management primitives such as
-\emph on 
-_malloc()
-\emph default 
- and 
-\emph on 
-_free()
-\emph default 
-, requires specific definitions:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-#define\SpecialChar ~
-_MPOOLS\SpecialChar ~
-<value>
-\emph default 
- This is the number of internal 
-\emph on 
-pool_t
-\emph default 
- which are necessary to initialize for an 
-\emph on 
-mpool_t
-\emph default 
-, to be able to use these efficient pools when dealing with byte requirements
- which are too small to be rounded at page boundaries.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-#define\SpecialChar ~
-_MPOOLSTART\SpecialChar ~
-<value>
-\emph default 
- The smallest amount of bytes which an 
-\emph on 
-mpool_t
-\emph default 
- can allocate, which is multiplied by two for each consecutive 
-\emph on 
-pool_t
-\emph default 
- initialized for the 
-\emph on 
-mpool_t
-\emph default 
- at 
-\emph on 
-mpool_init()
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-#define\SpecialChar ~
-_MPOOLSTEP\SpecialChar ~
-<value>
-\emph default 
- The number of physical 
-\emph on 
-_PAGE_SIZE
-\emph default 
- bytes pages into a 
-\emph on 
-page_t
-\emph default 
- for every 
-\emph on 
-pool_t
-\emph default 
- of an 
-\emph on 
-mpool_t
-\emph default 
-.
-\layout Standard
-
-To explain better the previous definitions, what the 
-\emph on 
-mpool_init()
-\emph default 
- function actually does is iterate 
-\emph on 
-_MPOOLS
-\emph default 
- times to initialize the 
-\emph on 
-pool_t
-\emph default 
- objects, setting the first 
-\emph on 
-pool_t
-\emph default 
- to allocate units of 
-\emph on 
-_MPOOLSTART
-\emph default 
- bytes, the second 
-\emph on 
-_MPOOLSTART
-\emph default 
- * 2, and continueing to iterate multiplying the unit size by two until
-\emph on 
-_MPOOLS
-\emph default 
- number of 
-\emph on 
-pool_t
-\emph default 
- were initialized.
- Larger unit sizes which cannot be handled by the 
-\emph on 
-pool_t
-\emph default 
- will be rounded at page boundaries.
-\emph on 
-_MPOOLSTEP
-\emph default 
- simply consists of the 
-\emph on 
-stepp
-\emph default 
- argument to 
-\emph on 
-pool_init()
-\emph default 
-.
- As such, all the definitions above intimately correlate to eachother, and
- are quite versatile to match various requirements an architecture may need.
-\layout Standard
-
-For a system with a 
-\emph on 
-_PAGE_SIZE
-\emph default 
- of 4096 bytes, an 
-\emph on 
-_MPOOLSTART
-\emph default 
- of 16 and 
-\emph on 
-_MPOOLSTEP
-\emph default 
- of 1, 7 consists of an ideal value for 
-\emph on 
-_MPOOLS
-\emph default 
-.
- On a system with a fair amount of memory, if it is wanted to minimize calls
- to the page management primitives even more, it is possible to set a larger
-\emph on 
-_MPOOLSTEP
-\emph default 
- and raise 
-\emph on 
-_MPOOLS
-\emph default 
- accordingly, while keeping the same underlaying 
-\emph on 
-_PAGE_SIZE
-\emph default 
-.
- Basically 
-\emph on 
-_MPOOLS
-\emph default 
- should be set just below the 
-\emph on 
-pool_init()
-\emph default 
- breaking point, where it returns FALSE because 
-\emph on 
-sizeof(mnode_t)
-\emph default 
- plus the current 
-\emph on 
-_MPOOLSTART
-\emph default 
- multiple consist of too large objects to fit into a 
-\emph on 
-pool_t
-\emph default 
- page (which in turn depends on 
-\emph on 
-_MPOOLSTEP
-\emph default 
- which changes the 
-\emph on 
-page_t
-\emph default 
- size for a 
-\emph on 
-pool_t
-\emph default 
-).
-\layout Standard
-
-It is recommended to read the source for 
-\emph on 
-mpool_init()
-\emph default 
- which is located in 
-\emph on 
-src/common/kernel/memory.c
-\emph default 
- for a better understanding, as well as the documentation on Xisop memory
- management primitives.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-enum\SpecialChar ~
-_memtypes
-\emph default 
- This enumeration should define the various memory types the architecture
- provides, in preference order when 
-\emph on 
-_MEM_ANY
-\emph default 
- is used (-1) when calling the allocation primitives.
- The enumeration should set 
-\emph on 
-_MEM_
-\emph default 
-* names, the first one corresponding to 0, and the last element should consist
- of 
-\emph on 
-_MEM_MAX
-\emph default 
-, corresponding to the number of memory types the system provides.
- Not all architectures provide more than a single memory type, under which
- case 
-\emph on 
-_MEM_ALL
-\emph default 
- will correspond to 0 and 
-\emph on 
-_MEM_MAX
-\emph default 
- to 1, respectively.
-\layout Standard
-
-Other than defining these requirements in it's 
-\emph on 
-support.h
-\emph default 
- headerfile, the port-specific initialization code is responsible for attaching
- the available physical memory pages to the system pools, before initializing
- the public interrupt facilities.
- This is done by first calling the 
-\emph on 
-memory_init()
-\emph default 
- machine-independent function.
- Then, the
-\emph on 
- mchunk_init()
-\emph default 
- and 
-\emph on 
-mchunk_attach()
-\emph default 
- functions which are documented in the Xisop memory management section are
- normally called once for each contiguous memory area which is to be used
- as general purpose memory.
- The video memory, or other special memory sections should not be included
- in the system memory pools.
- It is important to perform this step before continuing on with the next
- initialization sections.
- The 
-\emph on 
-mchunk_init()
-\emph default 
- and 
-\emph on 
-mchunk_attach()
-\emph default 
- functions are described in detail in the Xisop memory management section.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-memory_init(void
-\emph default 
-) This function is only called once by the port-specific initialization
- code before starting to attach memory chunks to the system pools.
- After this function executes, it becomes possible to use the 
-\emph on 
-mchunk_init()
-\emph default 
- and 
-\emph on 
-mchunk_attach()
-\emph default 
- functions to attach contiguous memory regions to the system page pools.
-\layout Paragraph
-
-Exceptions initialization and public interrupt facilities
-\layout Standard
-
-It is recommended to maintain an 
-\emph on 
-_interrupt_depth
-\emph default 
- variable or recursive lock, which each trap or interrupt handler should
- increase at startup and decrease before returning, which can be used for
- the scheduler interrupt to determine if it should call 
-\emph on 
-schedule()
-\emph default 
- or not.
- As the scheduler timer interrupt would also raise it at startup, it can
- then mask interrupts and evaluate if it equals 1 afterwards, in which case
- it is sure to have the right to perform a context switch.
- This permits to make system calls uninterruptible for the time of their
- execution and to protect the scheduler from performing context switches
- while an interrupt handler is executing, which at occasions could result
- in recursivity and context corruption.
- As an effort is made to minimize the number of system call traps required
- during normal Xisop function, the preemptive nature of the scheduler is
- not bothered by having uninterruptible system calls, unless a task voluntarily
- abuses 
-\emph on 
-sys_custom()
-\emph default 
-, which is by all meals legal if one wants to.
-\layout Standard
-
-Obviously, most exception handlers are responsible to return with the registers
- unchanged, and as such should normally save all general-purpose registers
- on the stack at startup, and return them before returning.
- This is especially true if C functions are to be called from the interrupt
- handler, where unexpected registers may be tempered with.
-\layout Standard
-
-After setting up the memory, the public interrupt facilities can be defined
- to the system and their internal handler vectors setup.
- Usually, 
-\emph on 
-facilities_init()
-\emph default 
- will be called before vectors are initialized, or if not possible, dummy
- do-nothing vectors can be installed, and can then be setup definitely after
- calling f
-\emph on 
-acilities_init()
-\emph default 
-, when it becomes safe.
-\layout Standard
-
-This function call depends on the 
-\emph on 
-enum _facilities
-\emph default 
- C enumerator which should be defined in the port specific 
-\emph on 
-support.h
-\emph default 
- headerfile.
- This enumerator defines each facility in the form of 
-\emph on 
-_FACILITY_
-\emph default 
-*, where * consists of the name of the facility.
- The first entry should evaluate to 0, and the last one to the total number
- of facilities (
-\emph on 
-_FACILITY_MAX
-\emph default 
-).
- The various interrupt handlers need to internally call 
-\emph on 
-facility_exechooks()
-\emph default 
- on the facility they are serving for the public facilities to become alive.
- At it's discretion, the handler may temporarily disable the interrupt source
- when calling the function, but 
-\emph on 
-facility_exechooks()
-\emph default 
- internally performs recursion prevention and makes sure to not execute
- the hooks if a hook is currently being inserted or removed, using an 
-\emph on 
-_rlock_t
-\emph default 
- for each facility internally.
-\layout Standard
-
-There only is at least one facility which is required for all ports to provide.
- This facility should be named 
-\emph on 
-_FACILITY_SCHEDTIMER
-\emph default 
-, and should call the hooks at 
-\emph on 
-_SCHEDTIMER_HZ
-\emph default 
- frequency, which should also be defined by the port-specific 
-\emph on 
-support.h
-\emph default 
-.
- This way, simple time-based Xisop applications can work portably on all
- ports.
- This facility should correspond to the timer interrupt which the port chose
- to use for the preemptive scheduler timer.
- This facility does not interfere with the scheduler activities; it is called
- when the interrupt occurs even if the scheduler 
-\emph on 
-rlock_t
-\emph default 
- is set (
-\emph on 
-schedule()
-\emph default 
- handles the scheduler locked/disabled case already).
- Generally, the scheduler interrupt handler works as follows:
-\layout Itemize
-
-Increase the global 
-\emph on 
-_interrupt_depth
-\emph default 
- variable like for all handlers
-\layout Itemize
-
-Temporarily disable the interrupt source (by raising the IPL using 
-\emph on 
-_spl
-\emph default 
-*
-\emph on 
-()
-\emph default 
- or otherwise) to prevent any possible recursion or other interruption.
-\layout Itemize
-
-Save the current user CPU context to the 
-\emph on 
-root->curctx _ctx_t
-\layout Itemize
-
-Execute the facility hooks using 
-\emph on 
-facility_exechooks(_FACILITY_SCHEDTIMER)
-\layout Itemize
-
-Verify if the 
-\emph on 
-_interrupt_depth
-\emph default 
- variable equals to 1.
- If so, call 
-\emph on 
-schedule(NULL)
-\emph default 
-, which may or may not change the 
-\emph on 
-root->curctx
-\emph default 
- backed up context pointer and 
-\emph on 
-root->curtask
-\layout Itemize
-
-Load back the CPU context from the new 
-\emph on 
-root->curctx
-\emph default 
- (which possibly can be the same, but this must not be assumed)
-\layout Itemize
-
-Re-enable the scheduler interrupt source
-\layout Itemize
-
-Decrease the global 
-\emph on 
-_interrupt_depth
-\emph default 
- variable like for other handlers
-\layout Itemize
-
-Return from interrupt handler while ensuring to jump to the PC of the new
- context.
- Generally, the address to return to is backed up into the supervisor stack,
- which needs to be modified for this.
- That address within the supervisor stack pointer is where context save
- and load operations obtain and set the Program Counter address.
-\layout Standard
-
-Because of the context load/save operations, and return address hack, the
- scheduler interrupt handler is usually implemented entirely in assembly
- (although it calls the 
-\emph on 
-schedule()
-\emph default 
- and 
-\emph on 
-facility_exechooks()
-\emph default 
- C functions).
-\layout Standard
-
-The other facilities, which are optional and can be provided by the port-specifi
-c code will often be implemented as a mix of assembly and C code and will
- similarily at least:
-\layout Itemize
-
-increase global 
-\emph on 
-_interrupt_depth
-\emph default 
- and optionally disable interrupt source
-\layout Itemize
-
-save registers
-\layout Itemize
-
-perform any additional wanted operation
-\layout Itemize
-
-call 
-\emph on 
-facility_exechooks()
-\emph default 
- on their facility
-\layout Itemize
-
-restore registers
-\layout Itemize
-
-re-enable the interrupt source if it was temporarily disabled, and decrease
- global 
-\emph on 
-_interrupt_depth
-\layout Itemize
-
-return
-\layout Standard
-
-The facility public interface and 
-\emph on 
-facility_exechooks()
-\emph default 
- are described in more details in the Xisop public facilities section.
-\layout Paragraph
-
-System trap triggers and handlers initialization
-\layout Standard
-
-It is important for the port-specific code to define the 
-\emph on 
-_syscall()
-\emph default 
- and 
-\emph on 
-_yield()
-\emph default 
- functions.
- The role of the system call trap handler is to serve system call functions
- uninterruptibly, internally calling 
-\emph on 
-_scatch()
-\emph default 
- Xisop common function with the requested arguments.
- Here is described the trigger, which function should be supplied by the
- port-dependent code:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_syscall(u_int32_t\SpecialChar ~
-function,\SpecialChar ~
-void\SpecialChar ~
-*res,\SpecialChar ~
-void\SpecialChar ~
-*args)
-\emph default 
- Internally places the supplied parameters into a static buffer or in registers,
- and generate a processor trap interrupt.
- It is safe to save the registers we modify on the stack, and restore them
- from the stack after the trap returns, and then return ourselves, because
- nor 
-\emph on 
-_yield()
-\emph default 
- nor context switching are implemented via syscalls.
- Although the understanding of the arguments is not necessary at this point,
-\emph on 
-function
-\emph default 
- specifies the syscall number which is to be performed, 
-\emph on 
-res
-\emph default 
- a pointer to eventual results expected from that system call (or NULL),
- and 
-\emph on 
-args
-\emph default 
- optional arguments which need to be passed to the system call (or NULL).
- Although this function is also highly processor-specific, the choice of
- the trap vector to implement system calls is left to the port writer, and
- as such this function as well.
-\layout Standard
-
-The other end, consisting of the system call trap handler, is responsible
- for the following:
-\layout Itemize
-
-Increment 
-\emph on 
-_interrupt_depth
-\emph default 
- global variable
-\layout Itemize
-
-Save all general purpose registers
-\layout Itemize
-
-Read arguments supplied by 
-\emph on 
-_syscall()
-\emph default 
- from the static buffer or registers, and insert them on the stack as C
- arguments, then call 
-\emph on 
-_scatch()
-\emph default 
- C function.
- Fix the stack pointer to forget the pushed stack arguments.
-\layout Itemize
-
-Restore general purpose registers we saved
-\layout Itemize
-
-Decrement 
-\emph on 
-_interrupt_depth
-\emph default 
- global variable
-\layout Itemize
-
-Return
-\layout Standard
-
-The 
-\emph on 
-_scatch()
-\emph default 
- function (which is defined in 
-\emph on 
-src/common/kernel/syscall.c
-\emph default 
-) is responsible for performing the necessary sanity checking on the arguments,
- and does not need to be provided by the machine-specific code:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_scatch(u_int32_t\SpecialChar ~
-function,\SpecialChar ~
-void\SpecialChar ~
-*results,\SpecialChar ~
-void\SpecialChar ~
-*arguments)
-\emph default 
- Consists of the heart of the syscall trap.
-\emph on 
-function
-\emph default 
- specifies the requested syscall function number which was called.
- These are standard and are described in the 
-\begin_inset Quotes eld
-\end_inset 
-
-System Calls
-\begin_inset Quotes erd
-\end_inset 
-
- section.
-\emph on 
-results
-\emph default 
- consists of a pointer to the block of memory which will be modified to
- store the syscall results by this 
-\emph on 
-function
-\emph default 
-.
- It can be NULL.
-\emph on 
-arguments
-\emph default 
- similarly specifies the location of the arguments expected for this 
-\emph on 
-function
-\emph default 
-, or NULL.
- This function refuses to perform any call if the supplied 
-\emph on 
-function
-\emph default 
- is invalid (out of bounds).
-\layout Standard
-
-After setting up the 
-\emph on 
-_syscall()
-\emph default 
- trap vector, the interrupts can remain disabled/masked still, like since
- the beginning.
- More information on the generic user system calls interface is provided
- in the Xisop system calls section.
-\layout Standard
-
-Another requirement that the port-specific code must satisfy consists of
- the 
-\emph on 
-_yield()
-\emph default 
- internal function:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-_yield(task_t\SpecialChar ~
-*task)
-\emph default 
- permits the current task to immediately perform a context switch to another
- task, in fact preempting itself.
-\emph on 
-task
-\emph default 
- is an optional preference of which task to switch to, or NULL, which parameter
- should be passed when the trap handler internally calls 
-\emph on 
-schedule()
-\emph default 
-.
- This is usually implemented in the form of a trap like for 
-\emph on 
-_syscall()
-\emph default 
-, which sets the supplied argument in a static buffer to prevent modifying
- a register (it is unsafe to save registers on the stack as we most likely
- won't be the next task to return from the trap).
- The backend trap handler acts as follows:
-\layout Itemize
-
-Increase the global 
-\emph on 
-_interrupt_depth
-\emph default 
- variable like for all handlers
-\layout Itemize
-
-Temporarily disable all interrupt sources (by raising the IPL using 
-\emph on 
-_splhigh()
-\emph default 
- or equivalent to prevent any possible interruption, but without modifying
- registers, which can be saved and restored safely before performing the
- next steps
-\layout Itemize
-
-Save the current user CPU context to the 
-\emph on 
-root->curctx _ctx_t
-\layout Itemize
-
-Insert the supplied argument from the static buffer in the stack as a C
- argument
-\layout Itemize
-
-Call 
-\emph on 
-schedule()
-\emph default 
-, which may or may not change the 
-\emph on 
-root->curctx
-\emph default 
- backed up context pointer and 
-\emph on 
-root->curtask
-\layout Itemize
-
-Adjust stack pointer to forget the passed argument
-\layout Itemize
-
-Load back the CPU context from the new 
-\emph on 
-root->curctx
-\emph default 
- (which possibly can be the same, but this must not be assumed)
-\layout Itemize
-
-Re-enable interrupts calling 
-\emph on 
-_spl0()
-\emph default 
- or performing equivalent taking care not to modify registers.
- Using the stack is now safe.
- (remember that the old level obtained from 
-\emph on 
-_splhigh()
-\emph default 
- cannot be obtained back unless saved to a static buffer, in which case
- it can be restored properly.
- Saving it on the stack is also safe if the context switching function only
- modified the user stack pointer and the supervisor stack pointer consists
- of the active stack during the trap).
-\layout Itemize
-
-Decrease the global 
-\emph on 
-_interrupt_depth
-\emph default 
- variable like for other handlers
-\layout Itemize
-
-Return from interrupt handler while ensuring to jump to the PC of the new
- context.
- Generally, the address to return to is backed up into the supervisor stack,
- which needs to be modified for this.
- That address within the supervisor stack pointer is where context save
- and load operations obtain and set the Program Counter address.
-\layout Paragraph
-
-Suggestions
-\layout Standard
-
-The rest of the port-specific code internals which it needs to perform are
- left to the implementor, as long as they suit well the purpose.
- However, a few suggestions are made which can help to keep some consistency
- among the various ports, in their choice of function names for instance.
- This example attempts to restrict the assembly code to the minimum, while
- calling C functions as much as possible to handle most exception code.
-\layout Standard
-
-It is generally a good idea for hardware interrupts to provide one separate
- assembly handler per interrupt level, to prevent the C code from having
- to perform unnecessary additional conditional instructions to evaluate
- the level, as it already usually needs to detect the source.
- For other general-purpose trap vectors, it is allowed to provide support
- to execute a single C function for all of them, passing in an argument
- the required information on the trap vector number.
- This however would be less desireable than having a different facility
- for each, if their frequency was high and a large number of hooks were
- attached, because they then would obviously all run often, evaluating one
- by one if they are interested in the trap.
- Suggestion names for various common facility types are shown in the Xisop
- public interrupt facilities section.
-\layout Standard
-
-It is to be noted that the timer interrupt chosen to be used as the preemptive
- scheduler one is special as it needs to perform context switching, often
- also implying stack pointer access and modifications.
- This handler is therefore usually fully written in assembly, as previously
- demonstrated.
- As a general rule, the role of the exception vectors is to call a C function
- which can then handle the event.
-\layout Standard
-
-Here are various C functions which can be called by the machine language
- backend to exceptions, traps and interrupts:
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_icatch
-\emph default 
-n
-\emph on 
-(void)
-\emph default 
- For every hardware interrupt level, une such C function can be called.
- For interrupt level 3, 
-\emph on 
-icatch3()
-\emph default 
- would be called, for instance.
- It is possible to pass parameters if required to detect the interrupt source
- in the C functions.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_tcatch(int\SpecialChar ~
-vector)
-\emph default 
- This C function can be called for all software traps which occur that do
- not correspond to the syscall or yield trap vectors.
-\emph on 
-vector
-\emph default 
- argument specifies the number of the trap vector.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_ecatch(int\SpecialChar ~
-vector)
-\emph default 
- A C function called when an hardware exception is generated, such as bus
- error, division by zero, etc.
- It is recommended that the code processing these do not hang or crash the
- system permanently if high-reliability is required.
-\emph on 
-vector
-\emph default 
- consists of the exception vector, or reason which caused it, and 
-\emph on 
-stack
-\emph default 
- points as usual to the retrurn from exception address on the stack.
- Although this is CPU-specific, port-specific exception handling code may
- be provided.
-\layout Paragraph
-
-Port-specific system shared libraries to attach and system tasks to launch
-\layout Standard
-
-Although Xisop has a few common portable system libraries and tasks which
- it initializes at startup, it is ideal for the port-specific section to
- be able to describe which other tasks should be launched, and their parameters
- such as priority level, stack size, etc.
- To do this the port-specific code needs to provide the 
-\emph on 
-_port_init()
-\emph default 
- function which the Xisop init task will invoke and which then can use the
- required flexibility.
- It should be noted that as the init task only has a 4096 bytes stack, this
- function is expected to at least create a task with a larger stack if it
- needs to before performing it's own initialization if it overuses the stack.
- The kernel expects the current state to remain the same when the function
- returns (apart of course from the new libraries and tasks which may now
- exist and be resident).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-void\SpecialChar ~
-_port_init(void)
-\emph default 
- Port-specific function who's purpose is to attach the wanted port-specific
- libraries, and to launch the wanted port-specific tasks.
- This function is called by the Xisop 
-\emph on 
-init
-\emph default 
- task which runs with a stack of 4096 bytes, and runs in userstate mode
- like normal tasks.
-\layout Paragraph
-
-Last steps of the port-specific initialization code
-\layout Standard
-
-After switching to supervisor mode, setting up memory, system call and yield
- traps, as well as scheduler timer interrupt, and initializing the public
- interrupt facilities, port-specific initialization code is then complete,
- and it now should execute the following steps:
-\layout Itemize
-
-Call the machine-independent 
-\emph on 
-xisop_init()
-\emph default 
- function, which sets up various internal structures and disables the scheduler,
- and then internally calls
-\emph on 
- _spl0()
-\emph default 
- as interrupts finally become safe to enable.
-\layout Itemize
-
-Call the famous Xisop machine-independent 
-\emph on 
-main()
-\emph default 
- function which is expected to never return.
- If the processor currently runs into supervisor mode, it is necessary to
- drop to usermode before calling 
-\emph on 
-main()
-\emph default 
-.
- The role of this function is to enable the scheduler, launch the Xisop
-\emph on 
-init
-\emph default 
- task, which in turn will make sure to launch the 
-\emph on 
-task reaper
-\emph default 
- task, and call the port-dependent 
-\emph on 
-_port_init()
-\emph default 
- function which then can also attach and launch the wanted resources.
-\newline 
-Note that the 
-\emph on 
-main()
-\emph default 
- function with it's current stack becomes the initial context that the scheduler
- always switches to when there remains no tasks in the ready queue to run.
- As such, after launching the init task, it loops forever calling 
-\emph on 
-sys_idle()
-\emph default 
- system call which internall calls processor-specific 
-\emph on 
-_idle()
-\emph default 
-, which permits the processor to stop spinning until the next interrupt
- or trap event occurs.
-\layout Subsubsection
-
-Amiga
-\layout Itemize
-
-The Amiga port uses the 
-\emph on 
-processors/m68k
-\emph default 
- processor-specific code.
-\layout Itemize
-
-In addition to the m68k 
-\emph on 
-_spl
-\emph default 
-*
-\emph on 
-()
-\emph default 
- functions, the amiga low level library also supplies 
-\emph on 
-aspl
-\emph default 
-*
-\emph on 
-()
-\emph default 
- functions using INTENA control register for finer grained control to disable
- certain interrupts for a period of time.
- For instance, 
-\emph on 
-asplvblank()
-\emph default 
- disables the vertical blank interrupt, 
-\emph on 
-asplsched()
-\emph default 
- disables the scheduler, etc.
-\emph on 
-asplx()
-\emph default 
- is used to restore the previous state, as usual.
- For 
-\emph on 
-asplsched()
-\emph default 
-, a 
-\emph on 
-_lock_t
-\emph default 
- is used to turn the scheduler ON/OFF, so that the timer interrupt it ties
- to still can execute other code if required.
-\emph on 
-XXX
-\layout Itemize
-
-The chosen 
-\emph on 
-_syscall()
-\emph default 
- trap vector was 0.
-\layout Itemize
-
-The chosen 
-\emph on 
-_yield()
-\emph default 
- trap vector was 1.
-\layout Itemize
-
-The Amiga has four multi-purpose timers in it's two CIA chips.
- The use Xisop currently makes of them is as follows: CIA-A TimerA is reserved
- for keyboard timing, which is a hardware requirement.
- CIA-B Timer A is used by the Xisop scheduler, which generates high-level
- hardware interrupts of high priority (IPL 6).
- The B timers and TOD counters are unused and remain available for devices
- and user code for each CIA.
-\layout Itemize
-
-The two memory page pools (
-\emph on 
-ppool_t
-\emph default 
-) initialized at startup by 
-\emph on 
-_init_memory()
-\emph default 
- consist of one for CHIP RAM, and another one for FAST RAM.
- The 
-\emph on 
-enum _memtypes
-\emph default 
- as such set 
-\emph on 
-_MEM_FAST
-\emph default 
- to 0 and 
-\emph on 
-_MEM_CHIP
-\emph default 
- to 1, FAST memory being the prefered if 
-\emph on 
-_MEM_ANY
-\emph default 
- is used.
- Currently, the addresses mapped in the standard distribution are 0x - 0x
- for CHIP (enhanced 2 megabytes agnus chip (fatter)), and 0x00200000-0x00600000
- for FAST (usual 4 first megabytes of ZorroII memory found on A2000).
- This currently needs to be modified in the code itself as the booting process
- currently does not detect the available RAM amounts.
- The provided UAE Amiga Emulator configuration file which is configured
- as such can be located in the 
-\emph on 
-src/ports/amiga/boot
-\emph default 
- directory.
-\emph on 
-XXX
-\layout Itemize
-
-To setup the initial supervisor stack, the AmigaOS SuperState() exec.library
- call must be used to gain supervisor privileges.
- The SSP/A7 register can then be set to the proper location.
- To do this a special function is provided in assembly by the Amiga support
- library, 
-\emph on 
-void\SpecialChar ~
-_supervisor(u_int32_t\SpecialChar ~
-*sp,\SpecialChar ~
-size_t\SpecialChar ~
-ssize\SpecialChar ~
-void (*func)(void))
-\emph default 
- which allows to set the new entry point function and stack.
- To the provided 
-\emph on 
-stack
-\emph default 
- pointer will be additionned the supplied stack size 
-\emph on 
-ssize
-\emph default 
- automatically because of the stack which grows upwards.
- The supplied function 
-\emph on 
-func
-\emph default 
- is then given control to.
- This function is expected to never return.
-\the_end
diff --git a/Xisop/src/clean.sh b/Xisop/src/clean.sh
deleted file mode 100755 (executable)
index 2576fa9..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-# $Id: clean.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ./generic_makedefs.sh
-
-show cd processors/m68k
-./clean.sh
-show cd ../../ports/amiga
-./clean.sh
-show cd boot
-./clean.sh
-show cd ../../../common
-./clean.sh
-show cd ..
-show $L_RM processor port makedefs.sh
diff --git a/Xisop/src/common/clean.sh b/Xisop/src/common/clean.sh
deleted file mode 100755 (executable)
index 76a9ead..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-# $Id: clean.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ../generic_makedefs.sh
-
-show cd kernlib
-./clean.sh
-show cd ../kernel
-./clean.sh
-show cd ..
diff --git a/Xisop/src/common/kernel/clean.sh b/Xisop/src/common/kernel/clean.sh
deleted file mode 100755 (executable)
index d386a45..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-# $Id: clean.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ../../generic_makedefs.sh
-
-cleanlib .
-show $L_RM ar/*.a
diff --git a/Xisop/src/common/kernel/debug.c b/Xisop/src/common/kernel/debug.c
deleted file mode 100644 (file)
index 976e387..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-/* $Id: debug.c,v 1.3 2004/06/04 02:15:47 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/debug.h>
-#include <common/kernel/main.h>
-#include <common/kernlib/fifo.h>
-#include <common/kernlib/string.h>
-#include <config.h>
-
-
-
-#ifdef DEBUG
-
-
-
-static fifo8_t fifo;
-static u_int8_t *fifobuf;
-
-
-
-static size_t btoa(char *, u_int32_t);
-static size_t dtoa(char *, int32_t);
-static size_t utoa(char *, u_int32_t);
-static size_t xtoa(char *, u_int32_t);
-static void fifowrite(const char *, size_t);
-
-
-
-static const char ddigits[] = "0123456789";
-static const char xdigits[] = "0123456789ABCDEF";
-
-
-
-void debug_init(void)
-{
-    fifobuf = MALLOC(DEBUG);
-    FIFO_INIT(&fifo, fifobuf, DEBUG);
-    root->debugfifo = &fifo;
-    _lock_init(&root->debuglock);
-    /* Not ideal but considerably reduces kernel size compared to a static
-     * array buffer. Has the disadventage that debugging is only available
-     * after memory initialization.
-     */
-    debug_printf("Xisop debugging enabled\n");
-}
-
-
-void debug_printf(const char *fmt, ...)
-{
-    debug_va_list ap;
-    register char c;
-    register const char *ptr = fmt, *optr;
-
-    if (ptr == NULL)
-       return;
-
-    lock_acquire(&root->debuglock);
-
-    debug_va_start(ap, fmt);
-    optr = ptr;
-    while ((c = *ptr++) != '\0') {
-       if (c == '%') {
-           ptr--;
-           /* Output pending chars */
-           if (optr < ptr)
-               fifowrite(optr, ptr - optr);
-           ptr++;
-           /* "%\0" ! */
-           if ((c = *ptr++) == '\0') {
-               ptr--;
-               break;
-           }
-
-           /* Process debug_va_arg */
-           switch (c) {
-           case '%':
-               ptr--;
-               break;
-           case 'B':   /* Boolean */
-               {
-                   register bool t = debug_va_arg(ap, bool);
-
-                   if (t)
-                       fifowrite("TRUE", 4);
-                   else
-                       fifowrite("FALSE", 5);
-               }
-               break;
-           case 'b':   /* Binary 32-bit */
-               {
-                   char buf[34];
-
-                   btoa(buf, debug_va_arg(ap, u_int32_t));
-                   fifowrite(buf, 33);
-               }
-               break;
-           case 'c':   /* Character */
-               {
-                   char ch = debug_va_arg(ap, char);
-
-                   fifowrite(&ch, 1);
-               }
-               break;
-           case 'd':   /* 32-bit decimal */
-               {
-                   char buf[12];
-                   size_t len;
-
-                   len = dtoa(buf, debug_va_arg(ap, int32_t));
-                   fifowrite(buf, len);
-               }
-               break;
-           case 'p':   /* 32-bit pointer */
-               {
-                   char buf[11];
-                   register void *p = debug_va_arg(ap, void *);
-
-                   if (p != NULL) {
-                       xtoa(buf, (u_int32_t)p);
-                       fifowrite(buf, 10);
-                   } else
-                       fifowrite("NULL", 4);
-               }
-               break;
-           case 's':   /* String */
-               {
-                   register const char *s = debug_va_arg(ap, char *);
-
-                   if (s != NULL)
-                       fifowrite(s, strlen(s));
-                   else
-                       fifowrite("<NULL>", 6);
-               }
-               break;
-           case 'T':   /* Current task and PC address, no va_arg() */
-               {
-                   register task_t *t = CURTASK();
-                   register void *pc = root->curctx->pc;
-                   char str[24];
-                   register char *ptr = str;
-
-                   *ptr++ = '[';
-                   xtoa(ptr, (u_int32_t)t);
-                   ptr += 10;
-                   *ptr++ = '.';
-                   xtoa(ptr, (u_int32_t)pc);
-                   ptr += 10;
-                   *ptr++ = ']';
-                   *ptr = '\0';
-                   fifowrite(str, 23);
-               }
-           case 'u':   /* 32-bit unsigned decimal */
-               {
-                   char buf[11];
-                   size_t len;
-
-                   len = utoa(buf, debug_va_arg(ap, u_int32_t));
-                   fifowrite(buf, len);
-               }
-               break;
-           case 'x':   /* 32-bit hexadecimal */
-               {
-                   char buf[11];
-
-                   xtoa(buf, debug_va_arg(ap, u_int32_t));
-                   fifowrite(buf, 10);
-               }
-               break;
-           default:    /* Display %<c>, it's a bug, and we debug! */
-               {
-                   char s[2];
-
-                   s[0] = '%';
-                   s[1] = c;
-                   fifowrite(s, 2);
-               }
-               break;
-           }
-           /* Adjust optr for our pending chars record */
-           optr = ptr;
-       }
-    }
-    debug_va_end(ap);
-
-    /* Any pending chars remaining? */
-    if (optr < ptr)
-       fifowrite(optr, ptr - optr);
-
-    _lock_release(&root->debuglock);
-}
-
-
-/* XXX Need to work on stdarg-like system and vsnprintf() instead of everything
- * in debug_printf().
-void dprintf2(const char *file, const char *function, u_int32_t line,
-       const char *fmt, ...)
-{
-    debug_printf("%s:%s():%d - %s", file, func, line);
-}
-*/
-
-
-
-/* This function writes into the debug FIFO buffer in a way to cause automatic
- * recycling so that the last DEBUG bytes will always be available in the
- * history until read. We do not use the lock here, because we only want
- * full lines to be recorded, we let debug_printf() do it.
- */
-static void fifowrite(const char *buf, size_t len)
-{
-    register fifo8_t *f = &fifo;
-
-    while (len > 0) {
-       FIFO_PUT(f, buf);
-       buf++;
-       len--;
-    }
-
-    /* XXX This would be more efficient if it worked :) I need to debug this.
-    if (len == 1)
-       FIFO_PUT(f, buf);
-    else {
-       u_int8_t *ptr;
-       size_t size;
-       register size_t l = len;
-
-       if ((size = FIFO_AVAIL(f)) < l) {
-           l -= size;
-
-           while (size ) XXX;
-           size = l;
-           FIFO_FREE(f, &ptr, &size, l);
-       }
-
-       while (l > 0) {
-           FIFO_ALLOC(f, &ptr, &size, l);
-           memcpy(ptr, buf, size);
-           buf += size;
-           l -= size;
-       }
-    }
-    */
-}
-
-
-/* Allows to read data from the FIFO buffer. The bytes are unlinked from the
- * buffer dynamically when they are read.
- */
-size_t dread(char *buf, size_t len)
-{
-    register fifo8_t *f = &fifo;
-    register size_t l = len;
-
-    if (buf == NULL || len == 0)
-       return 0;
-
-    lock_acquire(&root->debuglock);
-
-    while (l > 0) {
-       if (FIFO_EMPTY(f))
-           break;
-       FIFO_GET(f, buf);
-       buf++;
-       l--;
-    }
-    len = len - l;
-
-    /* XXX Debug this more efficient alternative
-    if (len == 1) {
-       if (!FIFO_EMPTY(f))
-           FIFO_GET(f, buf);
-       else
-           len = 0;
-    } else {
-       u_int8_t *ptr;
-       int size;
-       register int l = len, i;
-
-       len = 0;
-       for (i = 0; i < 2 && l > 0; i++) {
-           FIFO_FREE(f, &ptr, &size, l);
-           if (size == 0)
-               break;
-           memcpy(buf, ptr, size);
-           buf += size;
-           len += size;
-           l -= size;
-       }
-    }
-    */
-
-    _lock_release(&root->debuglock);
-
-    return len;
-}
-
-
-/* Buffer should at least be 34 bytes. Performs 32-bit value to ASCII binary
- * convertion. Returns length of string.
- */
-static size_t btoa(char *buf, u_int32_t val)
-{
-    register int i;
-    register char *ptr = buf;
-
-    *ptr++ = '%';
-    for (i = 31; i > -1; i--)
-       *ptr++ = (val & (1L << i)) ? '1' : '0';
-    *ptr = '\0';
-
-    return (ptr - buf);
-}
-
-
-/* Buffer should be at least 12 bytes. Converts signed 32-bit value to decimal
- * ASCII representation. Returns length of string.
- */
-static size_t dtoa(char *buf, int32_t val)
-{
-    register int32_t v = val;
-    register char *ptr = buf;
-    register const char *d = ddigits;
-
-    if (v < 0) {
-       *ptr++ = '-';
-       v = -v;
-    }
-    for (; v > 9; v /= 10)
-       *ptr++ = d[v % 10];
-    *ptr++ = d[v];
-    *ptr = '\0';
-
-    return (ptr - buf);
-}
-
-
-/* Buffer should be at least 11 bytes. Unsigned 32-bit value to decimal ASCII
- * convertion. Returns length of string.
- */
-static size_t utoa(char *buf, u_int32_t val)
-{
-    register u_int32_t v = val;
-    register char *ptr = buf;
-    register const char *d = ddigits;
-
-    for (; v > 9; v /= 10)
-       *ptr++ = d[v % 10];
-    *ptr++ = d[v];
-    *ptr = '\0';
-
-    return (ptr - buf);
-}
-
-
-/* Buffer should be at least 11 bytes. Converts 32-bit value to hexadecimal
- * ASCII representation. Returns length of string.
- */
-static size_t xtoa(char *buf, u_int32_t val)
-{
-    register u_int32_t v = val;
-    register char *ptr = buf;
-    register const char *d = xdigits;
-    register int i;
-
-    *ptr++ = '0';
-    *ptr++ = 'x';
-    for (i = 32 - 4; i > -1; i -= 4)
-       *ptr++ = d[v >> i & 15];
-    *ptr = '\0';
-
-    return (ptr - buf);
-}
-#endif
diff --git a/Xisop/src/common/kernel/debug.h b/Xisop/src/common/kernel/debug.h
deleted file mode 100644 (file)
index 5f3f113..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/* $Id: debug.h,v 1.3 2004/06/04 02:15:47 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNEL_DEBUG_H
-#define KERNEL_DEBUG_H
-
-
-
-#include <common/types.h>
-#include <config.h>
-
-
-
-/* This implements various debugging primitives. Macros are defined
- * so that no debugging code be compiled in the kernel if DEBUG
- * is not defined.
- */
-
-
-
-#ifndef DEBUG
-
-/* Debugging disabled, ensure that unnecessary code doesn't get compiled in.
- * if (DEBUG_TRUE(condition)) will always cause the condition to be TRUE, while
- * if (DEBUG_FALSE(condition)) will always cause the condition to be FALSE.
- * DEBUG_PRINTF() will do nothing.
- */
-
-#define DEBUG_PRINTF(s, ...)
-#define DEBUG_READ(b, s)       0
-#define DEBUG_TRUE(c)          /* CONSTCOND */1
-#define DEBUG_FALSE(c)         /* CONSTCOND */0
-
-#else
-
-/* Debugging enabled, macros must now do something */
-
-#define DEBUG_PRINTF           debug_printf
-#define DEBUG_READ(b, s)       debug_read(b, s)
-#define DEBUG_TRUE(c)          (c)
-#define DEBUG_FALSE(c)         (c)
-
-
-
-/* These should eventually be available even if no debugging is wanted.
- * However, these are really simple and are mostly made to serve 32-bit
- * values (although characters also work).
- */
-
-typedef u_int32_t *            debug_va_list;
-
-#define debug_va_start(a, l)   (a) = (u_int32_t *)(&(l) + sizeof(*(l)))
-#define debug_va_arg(a, t)     (t)(*a++)
-#define debug_va_copy(d, s)    (d) = (s)
-#define debug_va_end(a)
-
-
-
-void debug_init(void);
-void debug_printf(const char *, ...);
-/*void dprintf2(const char *, const char *, int, const char *, ...);*/
-size_t debug_read(char *, size_t);
-
-
-
-#endif
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/device.c b/Xisop/src/common/kernel/device.c
deleted file mode 100644 (file)
index c8105e8..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-/* $Id: device.c,v 1.8 2004/06/04 02:15:47 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/task.h>
-#include <common/kernel/device.h>
-#include <common/kernel/main.h>
-#include <common/kernel/object.h>
-#include <common/kernel/port.h>
-#include <common/kernel/signal.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/debug.h>
-#include <common/kernlib/string.h>
-#include <common/kernlib/hash.h>
-
-
-
-/* Allows current task to open a devicenode_t, obtaining a device_t handle */
-device_t *device_open(const char *name, u_int32_t ver, u_int32_t unit)
-{
-    device_t *dh = NULL;
-
-    if (name != NULL) {
-       register devicenode_t *dn;
-
-       SYSTABLE_RLOCK(SYSTABLE_DEVICES);
-       dn = (devicenode_t *)hashtable_lookup(SYSTABLE(SYSTABLE_DEVICES),
-                       name, strnlen(name, 32));
-       SYSTABLE_UNLOCK(SYSTABLE_DEVICES);
-       if (dn != NULL && (dn->version == ver || ver == 0)) {
-           if ((dh = (device_t *)spool_alloc(POOL_DEVICEHANDLE)) != NULL) {
-               if (dn->open(&dh->udata, unit)) {
-                   /* Validate object and set dependancy. We also register
-                    * it since iorequest_t depend on device_t.
-                    */
-                   OBJECT_VALIDATE(dh, OBJECT_DEVICEHANDLE);
-                   OBJECT_REGISTER(dh);
-                   OBJECT_SETDEP(dh, dn);
-                   dh->devnode = dn;
-                   dn->usecount++;
-                   /* Initialize other device_t fields */
-                   dh->devport = dn->port;
-                   dh->owner = CURTASK();
-                   dh->unit = unit;
-                   /* Attach to task resources for automatic freeing */
-                   SCHED_DISABLE();
-                   DLIST_APPEND(&CURTASK()->resources.devices, &dh->tasknode);
-                   SCHED_ENABLE();
-               } else {
-                   dh = (device_t *)spool_free(POOL_DEVICEHANDLE,
-                           (pnode_t *)dh);
-                   DEBUG_PRINTF("- %T device_open(%s, %u, %u) - Refused\n",
-                           name, ver, unit);
-               }
-           } else
-               DEBUG_PRINTF("* %T device_open(%s, %u, %u) - Out of memory\n",
-                       name, ver, unit);
-       } else
-           DEBUG_PRINTF("- %T device_open(%s, %u, %u) - Unknown device\n",
-                   name, ver, unit);
-    } else
-       DEBUG_PRINTF("* %T device_open(%s, %u, %u) - Illegal parameters\n",
-               name, ver, unit);
-
-    return dh;
-}
-
-
-/* Closes and frees a device_t from the task it belongs to */
-device_t *device_close(device_t *dh)
-{
-    if (OBJECT_VALID(dh, OBJECT_DEVICEHANDLE)) {
-       if (OBJECT_DEPENDS(dh, dh->devnode)) {
-           register devicenode_t *dn = dh->devnode;
-
-           SYSTABLE_RLOCK(SYSTABLE_DEVICES);
-           /* devicenode_t for this device_t still exists */
-           dn->close(dh->udata, dh->unit);
-           if ((--(dn->usecount)) == 0 && (dn->flags & DNF_RESIDENT) == 0) {
-               if (OBJECT_VALID(dn->task, OBJECT_TASK))
-                   signal_send(dn->task, SIGMASK(SIGTERM));
-           }
-           SYSTABLE_UNLOCK(SYSTABLE_DEVICES);
-       } else
-           DEBUG_PRINTF("* %T device_close(%p) - Device has died\n", dh);
-       /* Unlink task resource and free handle */
-       SCHED_DISABLE();
-       DLIST_UNLINK(&(dh->owner->resources.devices), &dh->tasknode);
-       SCHED_ENABLE();
-       OBJECT_INVALIDATE(dh);
-       spool_free(POOL_DEVICEHANDLE, (pnode_t *)dh);
-    } else
-       DEBUG_PRINTF("* %T device_close(%p) - Invalid device_t pointer\n",
-               dh);
-
-    return NULL;
-}
-
-
-/* Initializes an iorequest_t for use with specified device_t, necessary
- * before using it to send device requests.
- */
-bool iorequest_init(iorequest_t *req, device_t *dh, port_t *rport)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(dh, OBJECT_DEVICEHANDLE) &&
-           OBJECT_DEPENDS(dh, dh->devnode) &&
-           OBJECT_VALID(rport, OBJECT_PORT)) {
-       req->udata = NULL;
-       if (dh->devnode->iorinit == NULL ||
-               (req->udata = dh->devnode->iorinit()) != NULL) {
-           /* Validate object and register dependancy on device_t */
-           OBJECT_VALIDATE(req, OBJECT_IOREQUEST);
-           OBJECT_SETDEP(req, dh);
-           req->devhandle = dh;
-           /* Initialize other iorequest_t fields */
-           req->devport = dh->devport;
-           req->rport = rport;
-           req->flags = 0;
-           req->success = FALSE;
-           req->result = 0;
-           req->actual = 0;
-           ok = TRUE;
-       } else
-           DEBUG_PRINTF("* %T iorequest_init(%p, %p, %p) - Out of memory\n",
-                   req, dh, rport);
-    } else
-       DEBUG_PRINTF(
-               "* %T iorequest_init(%p, %p, %p) - Invalid device_t pointer\n",
-               req, dh, rport);
-
-    return ok;
-}
-
-
-bool iorequest_destroy(iorequest_t *req)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(req, OBJECT_IOREQUEST)) {
-       if (OBJECT_DEPENDS(req, req->devhandle) &&
-               OBJECT_DEPENDS(req->devhandle, req->devhandle->devnode)) {
-           register devicenode_t *dn = req->devhandle->devnode;
-
-           if (dn->iordestroy != NULL && req->udata != NULL)
-               dn->iordestroy(req->udata);
-       }
-       OBJECT_INVALIDATE(req);
-    } else
-       DEBUG_PRINTF(
-               "* %T iorequest_destroy(%p) - Invalid iorequest_t poinder\n",
-               req);
-
-    return ok;
-}
-
-
-/* Sends the iorequest_t message to it's corresponding device, and waits for
- * results to be obtained, then returns. This consists of a synchroneous
- * device request.
- */
-bool iorequest_sync(iorequest_t *req)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(req, OBJECT_IOREQUEST)) {
-       if ((req->flags & IOF_PENDING) == 0) {
-           if (port_send(req->devport, req->rport, (message_t *)req)) {
-               register sigmask_t sigmport = PORT_SIGMASK(req->devport);
-
-               req->flags = IOF_SYNC | IOF_PENDING;
-               while (((signal_wait(sigmport, NULL)) & sigmport) == 0) ;
-               port_get(req->devport);
-               /* Request satisfied */
-               req->flags &= ~(IOF_SYNC & IOF_PENDING);
-               ok = TRUE;
-           } else
-               DEBUG_PRINTF("* %T iorequest_sync(%p) - port_send()\n", req);
-       } else
-           DEBUG_PRINTF(
-                   "* %T iorequest_sync(%p) - iorequest_t already pending\n",
-                   req);
-    } else
-       DEBUG_PRINTF(
-               "* %T iorequest_sync(%p) - Invalid iorequest_t pointer\n",
-               req);
-
-    return ok;
-}
-
-
-/* Sends the iorequest_t message to it's corresponding device, but returns
- * immediately, without waiting for results. This consists of an asynchroneous
- * request. The application is responsible to monitor the reply port status
- * for the request completion, and to unqueue the reply from the reply port
- * before performing another request using this iorequest_t.
- */
-bool iorequest_async(iorequest_t *req)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(req, OBJECT_IOREQUEST)) {
-       if ((req->flags & IOF_PENDING) == 0) {
-           if (port_send(req->devport, req->rport, (message_t *)req)) {
-               req->flags = IOF_ASYNC | IOF_PENDING;
-               ok = TRUE;
-           } else
-               DEBUG_PRINTF("* %T iorequest_async(%p) - port_send()\n",
-                       req);
-       } else
-           DEBUG_PRINTF(
-                   "* %T iorequest_async(%p) - iorequest_t already pending\n",
-                   req);
-    } else
-       DEBUG_PRINTF(
-               "* %T iorequest_async(%p) - Invalid iorequest_t pointer\n",
-               req);
-
-    return ok;
-}
-
-
-/* Aborts a pending asynchroneous request which has not yet completed.
- * This in fact sends back a new request using the same iorequest_t, but
- * does not expect a reply back from the device for the abort request. However,
- * the reply port will be sent the reply as usual when the aborted iorequest_t
- * ends (which always happens even when a request is aborted).
- */
-bool iorequest_abort(iorequest_t *req)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(req, OBJECT_IOREQUEST)) {
-       if ((req->flags & IOF_PENDING) != 0 && (req->flags & IOF_ASYNC) != 0) {
-           req->function = IO_ABORT;
-           if (port_send(req->devport, req->rport, (message_t *)req)) {
-               req->flags |= IOF_ABORTING;
-               ok = TRUE;
-           } else
-               DEBUG_PRINTF("* %T iorequest_abort(%p) - port_send()\n",
-                       req);
-       } else
-           DEBUG_PRINTF(
-                   "* %T iorequest_abort(%p) - iorequest_t not pending\n",
-                   req);
-    } else
-       DEBUG_PRINTF(
-               "* %T iorequest_abort(%p) - Invalid iorequest_t pointer\n",
-               req);
-
-    if (!ok)
-       DEBUG_PRINTF("* %T iorequest_abort(%p)\n", req);
-
-    return ok;
-}
-
-
-/* Waits until the currently pending asynchroneous request completes. The reply
- * message is automatically unqueued from the reply port in this case.
- */
-bool iorequest_wait(iorequest_t *req)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(req, OBJECT_IOREQUEST)) {
-       if ((req->flags & IOF_PENDING) != 0 && (req->flags & IOF_ASYNC) != 0) {
-           register sigmask_t sigmport = PORT_SIGMASK(req->devport);
-
-           while (((signal_wait(sigmport, NULL)) & sigmport) == 0) ;
-           port_get(req->devport);
-           /* Request satisfied */
-           req->flags &= ~(IOF_ASYNC & IOF_PENDING);
-           ok = TRUE;
-       } else
-           DEBUG_PRINTF(
-                   "* %T iorequest_wait(%p) - iorequest_t not pending\n",
-                   req);
-    } else
-       DEBUG_PRINTF(
-               "* %T iorequest_wait(%p) - Invalid iorequest_t pointer\n",
-               req);
-
-    return ok;
-}
-
-
-/* Returns TRUE if the request is asynchroneous and still pending. */
-bool iorequest_pending(iorequest_t *req)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(req, OBJECT_IOREQUEST)) {
-       if ((req->flags & IOF_PENDING) != 0 && (req->flags & IOF_ASYNC) != 0)
-           ok = TRUE;
-    } else
-       DEBUG_PRINTF(
-               "* %T iorequest_pending(%p) - Invalid iorequest_t pointer\n",
-               req);
-
-    return ok;
-}
-
-
-/* Returns TRUE if the request last terminated by iorequest_abort(). */
-bool iorequest_aborted(iorequest_t *req)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(req, OBJECT_IOREQUEST)) {
-       if ((req->flags & IOF_ABORTED) != 0)
-           ok = TRUE;
-    } else
-       DEBUG_PRINTF(
-               "* %T iorequest_aborted(%p) - Invalid iorequest_t pointer\n",
-               req);
-
-    return ok;
-}
-
-
-/* Made for devices to satisfy a user iorequest_t, at the same time setting
- * the boolean result code for it.
- */
-bool iorequest_satisfy(iorequest_t *req, bool result)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(req, OBJECT_IOREQUEST)) {
-       if ((req->flags & IOF_PENDING) != 0) {
-           req->flags &= ~(IOF_PENDING | IOF_SYNC | IOF_ASYNC);
-           if ((req->flags & IOF_ABORTING) != 0) {
-               req->flags &= ~IOF_ABORTING;
-               req->flags |= IOF_ABORTED;
-               req->success = result;
-           }
-           if (!(ok = port_reply((message_t *)req)))
-               DEBUG_PRINTF(
-                       "* %T iorequest_satisfy(%p, %B) - port_reply(%p)\n",
-                       req, result, req);
-       }
-    } else
-       DEBUG_PRINTF("* %T iorequest_satisfy(%p, %B) - Invalid iorequest_t\n",
-               req, result);
-
-    return ok;
-}
-
-
-/* Allows a task to attach a new device to the system lists. It then of course
- * should serve requests through it's port. The task may only become one
- * device, that is, it may not attach more than a single device.
- * It however can serve multiple units on that device, of course.
- */
-bool device_attach(const char *name, u_int32_t version, port_t *port,
-       void (*clean)(void), bool (*open)(void **, u_int32_t),
-       void (*close)(void *, u_int32_t), void *(*iorinit)(void),
-       void (*iordestroy)(void *), u_int8_t flags)
-{
-    if (CURTASK()->resources.device == NULL && name != NULL &&
-           OBJECT_VALID(port, OBJECT_PORT) && open != NULL && close != NULL) {
-       register bstr_t *bstr;
-
-       if ((bstr = bstr_new(name, 32, FALSE)) != NULL) {
-           register devicenode_t *dn;
-
-           SYSTABLE_RLOCK(SYSTABLE_DEVICES);
-           if ((dn = (devicenode_t *)hashtable_lookup(
-                           SYSTABLE(SYSTABLE_DEVICES),
-                           bstr->data, bstr->len)) == NULL ||
-                   version != dn->version) {
-               if ((dn = (devicenode_t *)spool_alloc(POOL_DEVICENODE))
-                       != NULL) {
-                   /* Validate and register for dependancies */
-                   OBJECT_VALIDATE(dn, OBJECT_DEVICENODE);
-                   OBJECT_REGISTER(dn);
-                   /* Initialize other devicenode_t fields */
-                   dn->version = version;
-                   dn->name = bstr;
-                   dn->usecount = 0;
-                   dn->flags = flags;
-                   dn->port = port;
-                   dn->task = CURTASK();
-                   dn->clean = clean;
-                   dn->open = open;
-                   dn->close = close;
-                   dn->iorinit = iorinit;
-                   dn->iordestroy = iordestroy;
-                   /* Attach */
-                   SYSTABLE_UPGRADE(SYSTABLE_DEVICES);
-                   (void) hashtable_link(SYSTABLE(SYSTABLE_DEVICES),
-                                         (hashnode_t *)dn, bstr->data,
-                                         bstr->len, FALSE);
-                   SYSTABLE_UNLOCK(SYSTABLE_DEVICES);
-
-                   return TRUE;
-               } else
-                   DEBUG_PRINTF("* %T device_attach() - Out of memory\n");
-           } else
-               DEBUG_PRINTF(
-                       "* %T device_attach() - Device exists already\n");
-
-           SYSTABLE_UNLOCK(SYSTABLE_DEVICES);
-           bstr_free(bstr);
-       } else
-           DEBUG_PRINTF("* %T device_attach() - Out of memory\n");
-    } else
-       DEBUG_PRINTF("* %T device_attach() - Invalid parameters\n");
-
-    DEBUG_PRINTF("* %T device_attach(%s, %u, %p, %p, %p, %p, %p, %p, %x)\n",
-           name, version, port, clean, open, close, iorinit, iordestroy,
-           (u_int32_t)flags);
-
-    return FALSE;
-}
-
-
-bool device_detach(devicenode_t *dn)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(dn, OBJECT_DEVICENODE)) {
-       SYSTABLE_WLOCK(SYSTABLE_DEVICES);
-       hashtable_unlink(SYSTABLE(SYSTABLE_DEVICES), (hashnode_t *)dn);
-       SYSTABLE_UNLOCK(SYSTABLE_DEVICES);
-       if (dn->clean != NULL)
-           dn->clean();
-       OBJECT_INVALIDATE(dn);
-       if (dn->name != NULL)
-           bstr_free(dn->name);
-       spool_free(POOL_DEVICENODE, (pnode_t *)dn);
-    } else
-       DEBUG_PRINTF(
-               "* %T device_detach(%p) - Invalid devicenode_t pointer\n",
-               dn);
-
-    return ok;
-}
-
-
-
-/* Utility functions for very simple synchroneous I/O */
-
-/* Like read(), but on a Xisop device */
-ssize_t device_read(iorequest_t *req, void *buf, size_t size)
-{
-    ssize_t len = -1;
-
-    if (OBJECT_VALID(req, OBJECT_IOREQUEST)) {
-       req->function = IO_READ;
-       req->len = size;
-       req->data = buf;
-       if (iorequest_sync(req)) {
-           if (req->success)
-               len = req->actual;
-       } else
-           DEBUG_PRINTF(
-                   "* %T device_read(%p, %p, %u) - iorequest_sync(%p)\n",
-                   req, buf, size, req);
-    } else
-       DEBUG_PRINTF(
-               "* %T device_read(%p, %p, %u) - Invalid iorequest_t pointer\n",
-               req, buf, size);
-
-    return len;
-}
-
-
-/* Like write(), but on a Xisop device */
-ssize_t device_write(iorequest_t *req, void *buf, size_t size)
-{
-    ssize_t len = -1;
-
-    if (OBJECT_VALID(req, OBJECT_IOREQUEST)) {
-       req->function = IO_WRITE;
-       req->len = size;
-       req->data = buf;
-       if (iorequest_sync(req)) {
-           if (req->success)
-               len = req->actual;
-       } else
-           DEBUG_PRINTF(
-                   "* %T device_read(%p, %p, %u) - iorequest_sync(%p)\n",
-                   req, buf, size, req);
-    } else
-       DEBUG_PRINTF(
-               "* %T device_write(%p, %p, %u) - Invalid iorequest_t ptr\n",
-               req, buf, size);
-
-    return len;
-}
diff --git a/Xisop/src/common/kernel/device.h b/Xisop/src/common/kernel/device.h
deleted file mode 100644 (file)
index 7276d3a..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/* $Id: device.h,v 1.2 2004/01/18 17:42:59 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNEL_DEVICE_H
-#define KERNEL_DEVICE_H
-
-
-
-#include <common/types.h>
-#include <common/kernel/port.h>
-#include <common/kernel/task.h>
-#include <common/kernel/memory.h>
-#include <common/kernlib/list.h>
-#include <common/kernlib/hash.h>
-#include <common/kernlib/string.h>
-
-
-
-/* devicenode/device_t flags */
-#define DNF_RESIDENT           (1 << 0)
-
-/* iorequest_t flags */
-#define IOF_SYNC               (1 << 0)
-#define IOF_ASYNC              (1 << 1)
-#define IOF_PENDING            (1 << 2)
-#define IOF_ABORTING           (1 << 3)
-#define IOF_ABORTED            (1 << 4)
-
-/* Standard device commands */
-enum _devicecommands {
-    IO_ABORT = 0,
-    IO_READ,
-    IO_WRITE,
-    IO_CONTROL         /* General purpose like unix ioctl() */
-};
-
-
-
-/* For device task functions to access user data they associated with
- * device_t and iorequest_t handles (if any, or NULL).
- */
-#define DEVICEHANDLE_UDATA(d)  (d)->udata
-#define IOREQUEST_UDATA(r)     (r)->udata
-
-
-
-/* This structure holds the only necessary information which Xisop needs to
- * know. A device has to internally handle other information but which is of
- * no use to Xisop itself.
- */
-struct devicenode {
-    /* System link and information, for devices system list */
-    hashnode_t node;
-    u_int32_t version;
-    bstr_t *name;
-    u_int32_t usecount;
-    u_int8_t flags;
-    /* Validity sceal. device_t objects depend on us */
-    u_int32_t object_magic, object_id;
-
-    /* Port used to send device requests to */
-    port_t *port;
-    /* Task associated with device */
-    task_t *task;
-
-    /* Functions provided by device, described in Xisop documentation. */
-    void (*clean)(void);
-    bool (*open)(void **, u_int32_t);
-    void (*close)(void *, u_int32_t);
-    void *(*iorinit)(void);
-    void (*iordestroy)(void *);
-};
-
-/* Consists of a device handle, returned to tasks when opening a device */
-struct devicehandle {
-    pnode_t usernode;          /* Used by device for optional queuing */
-    node_t tasknode;           /* Used to remember task resource */
-    /* Validity and dependancy sceal, we depend on devicenode_t */
-    u_int32_t object_magic, object_id, objdep_magic, objdep_id;
-    devicenode_t *devnode;
-    /* Other fields */
-    task_t *owner;             /* Owner task of this handle */
-    port_t *devport;           /* Device port to use */
-    u_int32_t devnodeid;       /* Id of devnode */
-    u_int32_t unit;            /* Unit opened on device */
-    void *udata;               /* Device may link custom data here */
-};
-
-/* An iorequest_t consists of a message. This also means that the device task
- * may queue the message into custom list_t as required after they obtain it,
- * as long as they unlink it before they return it of course.
- */
-struct iorequest {
-    message_t msg;             /* An iorequest_t is a message */
-    /* Validity sceal and dependancy link */
-    u_int32_t object_magic, objdep_magic, objdep_id;
-    device_t *devhandle;
-    /* Other */
-    port_t *devport, *rport;
-    void *udata;
-    u_int8_t flags;
-
-    /* The following are the operation request control fields */
-    u_int32_t function, subfunction;
-    size_t len;
-    size_t offset;             /* Useful for block devices */
-    void *data;
-
-    /* And operation results fields */
-    bool success;
-    int result;
-    size_t actual;
-};
-
-
-
-/* User API functions */
-device_t *device_open(const char *, u_int32_t, u_int32_t);
-device_t *device_close(device_t *);
-bool iorequest_init(iorequest_t *, device_t *, port_t *);
-bool iorequest_destroy(iorequest_t *);
-bool iorequest_sync(iorequest_t *);
-bool iorequest_async(iorequest_t *);
-bool iorequest_abort(iorequest_t *);
-bool iorequest_wait(iorequest_t *);
-bool iorequest_pending(iorequest_t *);
-bool iorequest_aborted(iorequest_t *);
-
-/* Device task functions */
-bool iorequest_satisfy(iorequest_t *, bool);
-bool device_attach(const char *, u_int32_t, port_t *, void (*)(void),
-       bool (*)(void **, u_int32_t), void (*)(void *, u_int32_t),
-       void *(*)(void), void (*)(void *), u_int8_t);
-bool device_detach(devicenode_t *);
-
-/* Useful but very simple synchroneous functions */
-ssize_t device_read(iorequest_t *, void *, size_t);
-ssize_t device_write(iorequest_t *, void *, size_t);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/exception.c b/Xisop/src/common/kernel/exception.c
deleted file mode 100644 (file)
index 5fe0f7f..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/* $Id: exception.c,v 1.4 2004/06/04 02:15:47 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/main.h>
-#include <common/kernel/exception.h>
-#include <common/kernel/statistic.h>
-#include <common/kernel/debug.h>
-#include <common/kernlib/list.h>
-#include <processor/support.h>
-#include <port/support.h>
-
-
-
-/* These are the machine-independant kernel frontend to interrupt hooks
- * facilities. They internally use a recursive _rlock_t which allows to
- * ensure reliability when adding and removing hooks to a facility,
- * while removing the need for system call traps to access the functionality.
- */
-
-hookid_t hook_attach(u_int32_t facility, u_int32_t skipcount,
-       u_int32_t runcount, void (*code)(hookid_t, int, void *), void *data)
-{
-    register hookid_t id = 0;
-
-    if (facility < (enum _facilities)_FACILITY_MAX && code != NULL) {
-       register facility_t *f;
-       register hook_t *hook;
-
-       f = (facility_t *)&root->int_facilities[facility];
-       _rlock_acquire(&f->rlock);
-       if ((hook = (hook_t *)pool_alloc(&f->pool, FALSE)) != NULL) {
-           if (++f->idcnt == 0)
-               f->idcnt++;
-           id = hook->id = f->idcnt;
-           hook->skipcount = skipcount;
-           hook->runcount = runcount;
-           hook->code = code;
-           hook->data = data;
-           DLIST_APPEND(&f->hooks, (node_t *)hook);
-           STAT(STAT_HOOKS_ATTACHED, 1);
-       } else {
-           STAT(STAT_HOOKS_ATTACHED_NOMEM, 1);
-           DEBUG_PRINTF("* %T hook_attach() - Out of memory\n");
-       }
-       _rlock_release(&f->rlock);
-    } else {
-       STAT(STAT_HOOKS_ATTACHED_FAILED, 1);
-       DEBUG_PRINTF("* %T hook_attach(%u, %u, %u, %p, %p)\n",
-               facility, skipcount, runcount, code, data);
-    }
-
-    return id;
-}
-
-
-bool hook_detach(u_int32_t facility, hookid_t id)
-{
-    register bool ok = FALSE;
-
-    if (facility < (enum _facilities)_FACILITY_MAX && id != 0) {
-       register facility_t *f;
-       register hook_t *node, *next;
-
-       f = (facility_t *)&root->int_facilities[facility];
-       _rlock_acquire(&f->rlock);
-
-       for (node = DLIST_TOP(&f->hooks); node != NULL; node = next) {
-           next = DLIST_NEXT(node);
-           if (node->id == id) {
-               DLIST_UNLINK(&f->hooks, (node_t *)node);
-               pool_free((pnode_t *)node);
-               ok = TRUE;
-               STAT(STAT_HOOKS_DETACHED, 1);
-               break;
-           }
-       }
-       if (node == NULL)
-           STAT(STAT_HOOKS_DETACHED_NOEXIST, 1);
-
-       _rlock_release(&f->rlock);
-    } else {
-       STAT(STAT_HOOKS_DETACHED_FAILED, 1);
-       DEBUG_PRINTF("* %T hook_detach(%u, %u)\n", facility, id);
-    }
-
-    return ok;
-}
-
-
-void facility_disable(u_int32_t facility)
-{
-    if (facility < (enum _facilities)_FACILITY_MAX) {
-       _rlock_acquire(&(root->int_facilities[facility].rlock));
-       STAT(STAT_FACILITY_DISABLED, 1);
-    } else {
-       STAT(STAT_FACILITY_DISABLED_FAILED, 1);
-       DEBUG_PRINTF("* %T facility_disable(%u)\n", facility);
-    }
-}
-
-
-void facility_enable(u_int32_t facility)
-{
-    if (facility < (enum _facilities)_FACILITY_MAX) {
-       _rlock_release(&(root->int_facilities[facility].rlock));
-       STAT(STAT_FACILITY_ENABLED, 1);
-    } else {
-       STAT(STAT_FACILITY_ENABLED_FAILED, 1);
-       DEBUG_PRINTF("* %T facility_enable(%u)\n", facility);
-    }
-}
-
-
-/* This is called by the port-specific code to execute the hooks associated
- * with a facility. Note that a recursive lock is internally maintained which
- * ensures to prevent recursion, or to execute the hooks while new ones are
- * being added, or when a hook is being deleted.
- */
-
-
-/* Execute the hooks and transparently delete expired ones */
-void facility_exechooks(u_int32_t facility, int origin)
-{
-    if (facility < (enum _facilities)_FACILITY_MAX) {
-       register facility_t *f = &root->int_facilities[facility];
-
-       if (_rlock_try(&f->rlock)) {
-           register list_t *hooks = &f->hooks;
-           register hook_t *node, *tmp;
-
-           STAT(STAT_FACILITY_EXECUTED, 1);
-           node = DLIST_TOP(hooks);
-           while (node != NULL) {
-               if (node->skipcount > 0) {
-                   node->skipcount--;
-                   STAT(STAT_HOOKS_SKIPPED, 1);
-                   node = DLIST_NEXT(node);
-               } else {
-                   node->code(node->id, origin, node->data);
-                   STAT(STAT_HOOKS_EXECUTED, 1);
-                   if (node->runcount != 0) {
-                       tmp = DLIST_NEXT(node);
-                       if ((--node->runcount) == 0) {
-                           /* This hook is temporary and expired,
-                            * extract it.
-                            */
-                           DLIST_UNLINK(hooks, (node_t *)node);
-                           pool_free((pnode_t *)node);
-                           STAT(STAT_HOOKS_EXPIRED, 1);
-                       }
-                       node = tmp;
-                   } else
-                       node = DLIST_NEXT(node);
-               }
-           }
-           _rlock_release(&f->rlock);
-       } else
-           STAT(STAT_FACILITY_EXECUTED_LOCKED, 1);
-    } else {
-       STAT(STAT_FACILITY_EXECUTED_FAILED, 1);
-       DEBUG_PRINTF("* %T facility_exechooks(%u, %d)\n", facility, origin);
-    }
-}
-
-
-/* Initialize all facility_t */
-void facilities_init(void)
-{
-    register u_int32_t i;
-
-    for (i = 0; i < (enum _facilities)_FACILITY_MAX; i++) {
-       register facility_t *f = &root->int_facilities[i];
-
-       f->idcnt = 0;
-       _spl0();
-       pool_init(&f->pool, 1, 1, 1, sizeof(hook_t), 0);
-       _splhigh();
-       DLIST_INIT(&f->hooks);
-       _rlock_init(&f->rlock);
-       _rlock_acquire(&f->rlock);
-    }
-    for (i = 0; i < (enum _facilities)_FACILITY_MAX; i++) {
-       register facility_t *f = &root->int_facilities[i];
-
-       _rlock_release(&f->rlock);
-    }
-}
diff --git a/Xisop/src/common/kernel/exception.h b/Xisop/src/common/kernel/exception.h
deleted file mode 100644 (file)
index 760bdb6..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* $Id: exception.h,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNEL_EXCEPTION_H
-#define KERNEL_EXCEPTION_H
-
-
-
-#include <common/types.h>
-#include <common/kernel/memory.h>
-#include <common/kernlib/list.h>
-#include <processor/support.h>
-#include <port/support.h>
-
-
-
-/* Used to hold user code hooks which should be executed at exceptions
- * depending on the facility they are attached to.
- */
-struct _int_hook {
-    pnode_t node;
-    hookid_t id;
-    u_int32_t skipcount, runcount;
-    void (*code)(hookid_t, int, void *);
-    void *data;
-};
-
-/* There are _FACILITIES_MAX of these in the root->facilities array.
- * The facilities are defined by the port-specific code.
- */
-struct _int_facility {
-    hookid_t idcnt;
-    list_t hooks;
-    pool_t pool;
-    _rlock_t rlock;
-};
-
-
-hookid_t hook_attach(u_int32_t, u_int32_t, u_int32_t,
-       void (*)(hookid_t, int, void *), void *);
-bool hook_detach(u_int32_t, hookid_t);
-void facility_disable(u_int32_t);
-void facility_enable(u_int32_t);
-
-void facilities_init(void);
-void facility_exechooks(u_int32_t, int);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/main.c b/Xisop/src/common/kernel/main.c
deleted file mode 100644 (file)
index 8232cc7..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/* $Id: main.c,v 1.8 2004/06/04 02:25:15 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/main.h>
-#include <common/kernel/syscall.h>
-#include <common/kernel/scheduler.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/task.h>
-#include <common/kernel/port.h>
-#include <common/kernel/statistic.h>
-#include <common/kernel/debug.h>
-#include <common/kernlib/list.h>
-#include <common/kernlib/hash.h>
-#include <common/kernlib/string.h>
-#include <port/support.h>
-#include <processor/support.h>
-#include <config.h>
-
-
-
-COPYRIGHT("\0\nXisop Copyright 2001-2003, Matthew Mondor, \
-All rights reserved.\n");
-
-
-
-/* The famous global structure where all Xisop control information is stored */
-struct xisop_root root[1];
-
-static const char *systables_names[SYSTABLE_MAX] = {
-    "systable_publicports",
-    "systable_libraries",
-    "systable_devices",
-    "systable_handlers",
-    "systable_volumes"
-};
-
-
-
-/* Xisop main code. The port-specific code should switch to supervisor mode,
- * setup kernel stack, disable interrupts and setup it's interrupt handlers,
- * setup the memory ppools, call xisop_init(), switch back to usermode, and
- * jump definitively to this function.
- */
-int main(void)
-{
-    /* And we're Xisop-hosted! */
-
-    /* Setup and launch our main Xisop init task. It's source is in
-     * src/common/kernel/task.c.
-     */
-    {
-       register task_t *task;
-
-       if ((task = task_alloc(task_init, NULL, NULL, 0, 4096, TF_KERNEL))
-               != NULL)
-           task_start(task);
-    }
-
-    /* Here we enable the scheduler, which means that this current context
-     * will soon be the first to be saved in root->curctx, which currently
-     * consists of the _scontext _ctx_t buffer. When no more tasks are
-     * in the ready queue, _scontext will also be the restored context,
-     * in which case we want to avoid wasting power and overheating the
-     * CPU unnecessarily, and are using _idle() in an endless loop to do that.
-     * Because we are in usermode, we use sys_idle().
-     */
-    SCHED_ENABLE();
-
-    for (;;) {
-       /* Just idle processor */
-       /* XXX Amiga-specific, can be taken out, purple color on blitter to
-        * show that the system is all idle
-        */
-       CUSTOM->COLOR[0] = 0x0F0F;
-       sys_idle();
-    }
-
-    /* NOTREACHED */
-    return 0;
-}
-
-
-void xisop_init(void)
-{
-    /* Enable interrupts and therefore syscalls, facilities and scheduler
-     * timer as well. Note that until we SCHED_ENABLE(), the scheduler will
-     * not attempt to perform contex switches, even though the scheduler
-     * timer interrupt is enabled.
-     */
-
-#ifdef STATISTICS
-    statistic_init();
-#endif
-
-    /* Unique number generator */
-    _lock_init(&root->unique_lock);
-    root->unique = 0;
-
-    /* Kernel memory allocators */
-    _lock_init(&root->kernpool_lock);
-    spools_init();                     /* memory.h */
-    if ((root->kernpool = (mpool_t *)spool_alloc(POOL_MPOOL)) == NULL) {
-       /* XXX Panic */
-       CUSTOM->COLOR[0] = 0x0F00;
-    }
-    if (!mpool_init(root->kernpool)) {
-       /* XXX Panic */
-       CUSTOM->COLOR[0] = 0x0F00;
-    }
-
-    /* And task multitasking scheduler */
-    scheduler_init();                  /* scheduler.c */
-
-    /* Syscalls service */
-    syscall_init();
-
-#ifdef DEBUG
-    /* Debugging messages FIFO */
-    debug_init();
-#endif
-
-    /* System hash tables */
-    /* XXX Hmm the following calls kmalloc() which calls _kmalloc() which
-     * in turn calls lock_acquire(&root->kernpool_lock) which finally calls
-     * _yield(NULL) if it cannot immediately obtain the lock. However, _yield()
-     * function requires the scheduler interrupt to be running, and the
-     * scheduler lock to be released, of course. This appears to be the reason
-     * why the system now locks in trap_catch1() which corresponds to the
-     * _yield() handler... But, why can't the lock be obtained immediately?
-     * Since it is properly initialized first...
-     * I tried this in xisop_init(), in start of main() and in main() after
-     * SCHED_ENABLE(), always with the same results. Would it be possible that
-     * something we lock a lock, and are calling something which also attempts
-     * to lock it (and we already hold it)? If so, it would be either
-     * _kmalloc() or pages_alloc(). But they are both using a different lock..
-     * Or, would it be possible that I messed up port.c locking?
-     * XXX Oh! It works fine when I strip out DEBUG and STATISTICS. This
-     * probably means that the problem is the the xisop kernel size and boot
-     * loader which need adjusting.
-     */
-    {
-       register int i;
-
-       for (i = 0; i < (enum systables)SYSTABLE_MAX; i++) {
-           rwlock_init(&root->systables[i].lock);
-           if (!hashtable_init(SYSTABLE(i), systables_names[i],
-                       HT_DEFAULT_CAPACITY, kmalloc, kfree,
-                       memcmp, memhash32, TRUE)) {
-               /* XXX PANIC! */
-               CUSTOM->COLOR[0] = 0x0F00;
-           }
-       }
-    }
-
-    /* Enable interrupts */
-    _spl0();
-}
-
-
-u_int32_t unique_id(void)
-{
-    register u_int32_t id;
-
-    lock_acquire(&root->unique_lock);
-    id = (++root->unique);
-    _lock_release(&root->unique_lock);
-
-    return id;
-}
-
-
-hashtable_t *systable_lock(u_int32_t systable, bool exclusive)
-{
-    hashtable_t *list = NULL;
-
-    if (systable < (enum systables)SYSTABLE_MAX) {
-       if (exclusive)
-           SYSTABLE_WLOCK(systable);
-       else
-           SYSTABLE_RLOCK(systable);
-       list = SYSTABLE(systable);
-    }
-
-    return list;
-}
-
-
-void systable_unlock(u_int32_t systable)
-{
-    if (systable < (enum systables)SYSTABLE_MAX)
-       SYSTABLE_UNLOCK(systable);
-}
-
-
-void systable_upgrade(u_int32_t systable)
-{
-    if (systable < (enum systables)SYSTABLE_MAX)
-       SYSTABLE_UPGRADE(systable);
-}
diff --git a/Xisop/src/common/kernel/main.h b/Xisop/src/common/kernel/main.h
deleted file mode 100644 (file)
index 90dc56a..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/* $Id: main.h,v 1.5 2004/01/19 18:07:11 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNEL_MAIN_H
-#define KERNEL_MAIN_H
-
-
-
-#include <common/types.h>
-#include <common/kernel/scheduler.h>
-#include <common/kernel/task.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/statistic.h>
-#include <common/kernel/exception.h>
-#include <common/kernlib/list.h>
-#include <common/kernlib/string.h>
-#include <common/kernlib/fifo.h>
-#include <common/kernlib/hash.h>
-#include <processor/support.h>
-#include <port/support.h>
-#include <config.h>
-
-
-
-/* To access and manipulate system lists */
-#define SYSTABLE(l)    (&(root->systables[(enum systables)(l)].table))
-#define SYSLOCK(l)     (&(root->systables[(enum systables)(l)].lock))
-#define SYSTABLE_RLOCK(l)      rwlock_acquire(SYSLOCK(l), FALSE)
-#define SYSTABLE_WLOCK(l)      rwlock_acquire(SYSLOCK(l), TRUE)
-#define SYSTABLE_UNLOCK(l)     rwlock_release(SYSLOCK(l))
-#define SYSTABLE_UPGRADE(l)    rwlock_upgrade(SYSLOCK(l))
-
-
-/* A system list. The lock allows simultaneous read-only access, or exclusive
- * access when write operations are required.
- */
-struct systable {
-    rwlock_t lock;
-    hashtable_t table;
-};
-
-enum systables {
-    SYSTABLE_PUBLICPORTS = 0,
-    SYSTABLE_LIBRARIES,
-    SYSTABLE_DEVICES,
-    SYSTABLE_HANDLERS,
-    SYSTABLE_VOLUMES,
-    SYSTABLE_MAX
-};
-
-
-/* The Xisop main root structure */
-struct xisop_root {
-
-    /* Do not change the order of the following block fields, as port-specific
-     * assembly code may assume their offsets.
-     */
-
-    /* Scheduling */
-    _rlock_t sched_lock;
-    list_t tasks_ready, tasks_wait, tasks_dead;
-    task_t *curtask;
-    _ctx_t *curctx;
-
-    /* The remaining fields are only accessed by common C code. */
-    task_t *task_init, *task_reaper;
-
-    /* Memory management. First are the system page pools */
-    ppool_t ppools[(enum _memtypes)_MEM_MAX];
-    /* Then the system object pools */
-    _lock_t spools_locks[(enum _syspools)POOL_MAX];
-    pool_t spools[(enum _syspools)POOL_MAX];
-    /* And the kernel general purpose pool */
-    _lock_t kernpool_lock;
-    mpool_t *kernpool;
-
-    /* Interrupts abstraction system */
-    facility_t int_facilities[(enum _facilities)_FACILITY_MAX];
-
-   /* Various important system lists */
-    struct systable systables[(enum systables)SYSTABLE_MAX];
-
-    /* System calls */
-    void (**syscalls)(void *, void *);
-
-    /* Useful counter to create unique IDs for arbitrary objects, like for
-     * ports, using the UNIQUE() macro. Should normally be used when the
-     * scheduler is disabled.
-     */
-    _lock_t unique_lock;
-    u_int32_t unique;
-
-#ifdef STATISTICS
-    /* Statistics support */
-    u_int32_t stats[(enum stat_keys)STAT_MAX];
-#endif
-#ifdef DEBUG
-    /* dprintf() support */
-    _lock_t debuglock;
-    fifo8_t *debugfifo;
-#endif
-};
-
-
-
-/* xisop global data */
-extern struct xisop_root root[1];
-
-
-
-int main(void);
-void xisop_init(void);
-u_int32_t unique_id(void);
-
-hashtable_t *systable_lock(u_int32_t, bool);
-void systable_upgrade(u_int32_t);
-void systable_unlock(u_int32_t);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/make.sh b/Xisop/src/common/kernel/make.sh
deleted file mode 100755 (executable)
index fbd47d8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-# $Id: make.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ../../makedefs.sh
-
-buildlib .
-show $C_AR ar/kernel.a *.o
-show $C_RANLIB ar/kernel.a
diff --git a/Xisop/src/common/kernel/memory.c b/Xisop/src/common/kernel/memory.c
deleted file mode 100644 (file)
index 3811e14..0000000
+++ /dev/null
@@ -1,1425 +0,0 @@
-/* $Id: memory.c,v 1.9 2004/06/04 03:09:48 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Support for multiple memory types and dynamically attaching pages at
- * runtime was implemented the 25 Febuary 2003, when this code was rewritten
- * from scratch.
- *
- * This memory management system works with physical pages. This means that
- * we must provide facilities to work with actual physical contiguous pages
- * when large memory areas are required. Pages only consist of useful units
- * for management; They thus can be of any size (although multiples of 16
- * bytes), and do not need to correspond to the page size required by the
- * MMU system (if any).
- *
- * It may not be the best or most efficient way to deal with this, as I
- * wrote this code from scratch using my own ideas, without reference.
- * But it works well and seems quite fast. Moreover, _PAGE_SIZE, _MEM_MAX
- * and _MPOOLS are provided by the port-specific code, and allows to adapt
- * the system to a variety of situations. It thus well serves it's intended
- * purpose. We provide operations on pages, on basic fixed-sized pools and
- * multiple block size pools for general purpose memory management functions.
- *
- * A previous pool_t implementation attempted to not have to delete all the
- * nodes from a page when moving an unused page to the page cache, and
- * statistics would be kept to know when to free them, at which time their
- * pnode_t nodes were unlinked as well. Some care was taken to append freed
- * nodes of less used pages at the end of the list and insert freed nodes of
- * very used ones at the top of the list, so that over time hopefully
- * the system would stabilize well. It used to result in more fragmentation
- * than the current method which still caches unused pages and uses statistics
- * to free them less often, but immediately removes all nodes of a page from
- * the free nodes list when a page is unused, and has to re-initialize all
- * those nodes for a page when retreiving a page back from the cache.
- * Because Xisop works with actual physical pages and that it requires actual
- * contiguous pages for large data blocks, it is very important to do what is
- * necessary to avoid fragmentation as much as possible, in favor of stability
- * and performance over long uptimes periods, and so I reverted to this method.
- * We favor reuse of recently used nodes and pages as much as possible.
- *
- * It would be nice if the free list consisted of nodes linking to the next
- * contiguous pages block rather than only individual pages. This would speed
- * up multiple page allocations, which currently requires running among free
- * pages to locate contiguous ones. Possibly that freeing could also adapt
- * the pages index dynamically so that nodes could be restored without running
- * among individual pages to know where to insert the node.
- *
- * The system was first tested on NetBSD in userspace, to ensure that
- * everything works as expected before the code was imported in Xisop.
- *
- * Matt
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/main.h>
-#include <common/kernel/statistic.h>
-#include <common/kernel/syscall.h>
-#include <common/kernel/task.h>
-#include <common/kernel/object.h>
-#include <common/kernel/port.h>
-#include <common/kernel/scheduler.h>
-#include <common/kernel/device.h>
-#include <common/kernel/debug.h>
-#include <common/kernlib/list.h>
-#include <common/kernlib/string.h>
-#include <port/support.h>
-#include <processor/support.h>
-#include <config.h>
-
-
-
-/* Used by spools_init() */
-static const struct syspools_params syspools_params
-       [(enum _syspools)POOL_MAX] = {
-    {"tasks_pool", 1, 0, 0, sizeof(task_t)},
-    {"ports_pool", 1, 0, 0, sizeof(port_t)},
-    {"devicenodes_pool", 1, 0, 0, sizeof(devicenode_t)},
-    {"devices_pool", 1, 0, 0, sizeof(device_t)},
-    {"mpools_pool", 1, 0, 0, sizeof(mpool_t)}
-};
-
-
-
-/* This function is required to call once before initializing the memory
- * pages, by the port-specific code.
- */
-void memory_init(void)
-{
-    register u_int32_t i;
-
-    for (i = 0; i < (enum _memtypes)_MEM_MAX; i++) {
-       _lock_init(&root->ppools[i].lock);
-       DLIST_INIT(&root->ppools[i].mchunks);
-    }
-}
-
-
-/* This function is extremely useful to prepare a given contiguous memory area
- * for it to be attached to the system pages using mchunk_attach().
- * Sanity checking is performed to fix page alignment if needed, and the
- * internal control structures are automatically prepared.
- * Returns a pointer to an mchunk_t, or NULL if the supplied memory area is
- * too small (under two valid pages).
- */
-mchunk_t *mchunk_init(void *mem, size_t size)
-{
-    mchunk_t *mchunk = NULL;
-    void *begin, *end;
-    u_int32_t pages;
-
-    /* Page-align pointers, and calculate number of supplied memory pages */
-    end = mem + size;
-    begin = (void *)BALIGN_CEIL(mem, _PAGE_SIZE);
-    end = (void *)BALIGN_FLOOR(end, _PAGE_SIZE);
-    pages = (end - begin) / _PAGE_SIZE;
-
-    if (pages > 1) {
-       void *reserved;
-       page_t **index, *page;
-       u_int32_t extrapages;
-       size_t extrabytes;
-
-       /* Evaluate how many pages are required to be reserved to setup the
-        * mchunk_t and it's components. As we evaluate this on the number of
-        * available pages, which will shrink a bit after we reserve the area,
-        * we will re-evaluate it later, but will still be using the same
-        * reserved area, thus loosing a few bytes. The loss is however quite
-        * negligable.
-        */
-       extrabytes = (size_t)OALIGN_CEIL(sizeof(mchunk_t), u_int32_t);
-       extrabytes += (sizeof(page_t *) + sizeof(page_t)) * pages;
-       extrapages = extrabytes / _PAGE_SIZE;
-       if (extrabytes % _PAGE_SIZE)
-           extrapages++;
-       reserved = begin;
-       begin += extrapages * _PAGE_SIZE;
-       pages -= extrapages;
-
-       /* Now our necessary reserved area is at <reserved>, and has little
-        * more room than required to store all the control data. We have to
-        * setup <pages> pages, starting at <begin> and ending at <end>.
-        * First setup our control structures pointers.
-        */
-       mchunk = (mchunk_t *)reserved;
-       reserved += sizeof(mchunk_t);
-       reserved = (void *)OALIGN_CEIL(reserved, u_int32_t);
-       page = reserved;
-       reserved += sizeof(page_t) * pages;
-       reserved = (void *)OALIGN_CEIL(reserved, u_int32_t);
-       index = reserved;
-
-       /* Run through pages filling the control index and headers, while
-        * linking the page_t nodes into the mchunk_t.
-        */
-       DLIST_INIT(&mchunk->free);
-       mchunk->index = index;
-       mchunk->pages = pages;
-       {
-           register u_int8_t *run = begin;
-           register list_t *l = &mchunk->free;
-           register u_int32_t i;
-
-           for (i = 0; i < pages; i++, run += _PAGE_SIZE) {
-               register page_t *p = &page[i];
-
-               p->mchunk = mchunk;
-               p->address = run;
-               p->last = NULL;
-               p->id = i;
-               p->state = PS_FREE;
-               p->pool = NULL;
-               index[i] = p;
-               DLIST_APPEND(l, (node_t *)p);
-           }
-       }
-    }
-
-    if (mchunk != NULL)
-       OBJECT_VALIDATE(mchunk, OBJECT_MCHUNK);
-
-    return mchunk;
-}
-
-
-/* Allows to dynamically attach new memory at runtime. This can be useful
- * for instance to assign memory for a hotplug device such as PCMCIA RAM.
- * The mchunk_t should be setup using mchunk_init(). It is recommended to
- * read the Xisop documentation for more information. One of the existing
- * memory types supplied by the port-specific code should be chosen to which
- * attach the chunk. mchunk_attach() is also used by the port-specific code
- * to attach the initial memory pages.
- */
-bool mchunk_attach(int memtype, mchunk_t *mchunk)
-{
-    bool ok = FALSE;
-
-    if (memtype < (enum _memtypes)_MEM_MAX && memtype != _MEM_ANY &&
-           OBJECT_VALID(mchunk, OBJECT_MCHUNK)) {
-       register ppool_t *p;
-       register mchunk_t *m;
-
-       p = &root->ppools[memtype];
-       mchunk->ppool = p;
-
-       /* Obtain the system pages protection lock */
-       lock_acquire(&p->lock);
-
-       /* Make sure that this chunk is not already in the pool. We can
-        * afford this as this is a rare call, although dangerous.
-        */
-       DLIST_FOREACH(&p->mchunks, m) {
-           if (m == mchunk)
-               break;
-       }
-       if (m == NULL) {
-           DLIST_APPEND(&p->mchunks, (node_t *)mchunk);
-           ok = TRUE;
-           STAT(STAT_MCHUNKS_ATTACH, 1);
-       }
-
-       _lock_release(&p->lock);
-    }
-
-    if (!ok) {
-       STAT(STAT_MCHUNKS_ATTACH_FAILED, 1);
-       DEBUG_PRINTF("* %T mchunk_attach(%d, %p)\n", memtype, mchunk);
-    }
-
-    return ok;
-}
-
-
-/* Permits to dynamically detach memory at runtime, which was previously
- * attached using mchunk_attach(). Note that this function fails with FALSE
- * if any page of memory currently remains allocated, or if the mchunk_t is
- * not currently attached.
- */
-bool mchunk_detach(int memtype, mchunk_t *mchunk)
-{
-    bool ok = FALSE;
-
-    if (memtype < (enum _memtypes)_MEM_MAX && memtype != _MEM_ANY &&
-           OBJECT_VALID(mchunk, OBJECT_MCHUNK)) {
-       register ppool_t *p;
-       register mchunk_t *m;
-
-       p = &root->ppools[memtype];
-
-       /* Lock system pages safely lock */
-       lock_acquire(&p->lock);
-
-       /* Make sure that this chunk is attached in the expected memory type,
-        * and also make sure that all pages are free (unallocated).
-        */
-       DLIST_FOREACH(&p->mchunks, m) {
-           if (m == mchunk)
-               break;
-       }
-       if (m == mchunk) {
-           if (m->pages == DLIST_NODES(&m->free)) {
-               DLIST_UNLINK(&p->mchunks, (node_t *)m);
-               ok = TRUE;
-               STAT(STAT_MCHUNKS_DETACH, 1);
-           }
-       }
-
-       _lock_release(&p->lock);
-    }
-
-    if (!ok) {
-       STAT(STAT_MCHUNKS_DETACH_FAILED, 1);
-       DEBUG_PRINTF("* %T mchunk_detach(%d, %p)\n", memtype, mchunk);
-    }
-
-    return ok;
-}
-
-
-/* Requests obtention of one or more contiguous physical pages from the system.
- * Returns a pointer to the first page_t on success, or NULL on failure
- * (out of memory). If <zero> is true, the returned memory area will be
- * cleared to 0x00 bytes. To properly be freed, pages_free() is expected to
- * be called on the same supplied pointer, which will free back all pages
- * which were allocated at once with this function. On success,
- * pages_t->address can be used to access our requested memory.
- */
-page_t *pages_alloc(int memtype, u_int32_t many, bool zero)
-{
-    register ppool_t *fp = NULL, *tp = NULL;
-    page_t *pages = NULL;
-    bool ok;
-
-    /* If a memory type was specified, only run through that ppool_t, but
-     * run through each ppool_t in order otherwise until we satisfy the
-     * request. It is safe to do this interruptible as the memory types
-     * pools always remain static.
-     */
-    ok = TRUE;
-    if (many < 1)
-       ok = FALSE;
-    else {
-       if (memtype > -1) {
-           if (memtype < (enum _memtypes)_MEM_MAX) {
-               /* Will only try requested memory type */
-               fp = tp = &root->ppools[memtype];
-               tp++;
-           } else
-               ok = FALSE;
-       } else if (memtype == _MEM_ANY) {
-           /* Will try all memory types sequencially in order */
-           fp = &root->ppools[0];
-           tp = &root->ppools[(enum _memtypes)_MEM_MAX];
-           tp++;
-       } else
-           ok = FALSE;
-    }
-
-    if (ok) {
-       /* Loop through ppool_t types */
-       for (; fp < tp; fp++) {
-           register mchunk_t *m;
-
-           lock_acquire(&fp->lock);
-
-           /* Loop through mchunk_t nodes of the ppool_t */
-           DLIST_FOREACH(&fp->mchunks, m) {
-               /* Skip any mchunk_t which doesn't have enough pages */
-               if (DLIST_NODES(&m->free) >= many) {
-                   if (many == 1) {
-                       register page_t *p;
-
-                       /* No need to look for contiguous pages as only a
-                        * single one was requested. Detach the first page.
-                        */
-                       p = DLIST_TOP(&m->free);
-                       DLIST_UNLINK(&m->free, &p->node);
-                       p->node.next = p->node.prev = NULL;
-                       p->last = p;
-                       p->state = PS_ALLOCATED;
-                       _lock_release(&fp->lock);
-                       if (zero)
-                           pageclr(p->address, 1);
-                       pages = p;
-                       STAT(STAT_PAGES_ALLOC, 1);
-                       goto end;
-                   } else {
-                       register page_t *n, *o;
-                       register u_int32_t c, oid;
-
-                       /* Scan for <many> contiguous pages in this mchunk_t */
-                       c = 1;
-                       o = DLIST_TOP(&m->free);
-                       oid = o->id;
-                       for (n = DLIST_NEXT(o); n != NULL; n = DLIST_NEXT(n)) {
-                           if (++oid == n->id) {
-                               /* Contiguous, count and continue */
-                               c++;
-                               if (c == many)
-                                   break;
-                           } else {
-                               /* Not contiguous, reset and continue */
-                               c = 1;
-                               o = n;
-                           }
-                       }
-                       if (c == many) {
-                           register node_t *next, *prev;
-
-                           /* <many> contiguous pages were found, starting at
-                            * o and ending at n, unlink them all at once
-                            * efficiently and set last pointer.
-                            */
-                           prev = o->node.prev;
-                           next = n->node.next;
-                           if (prev)
-                               prev->next = next;
-                           else
-                               m->free.top = next;
-                           if (next)
-                               next->prev = prev;
-                           else
-                               m->free.bottom = prev;
-                           o->node.prev = n->node.next = NULL;
-                           o->last = n;
-                           m->free.nodes -= c;
-
-                           /* Then initialize the pages. Unfortunately
-                            * we need to perform this with lock held
-                            * because freeing pages runs among pages
-                            * looking for PS_FREE nodes.
-                            */
-                           for (n = o; c > 0;
-                                   n = (page_t *)n->node.next, c--)
-                               n->state = PS_ALLOCATED;
-
-                           /* Finished with system pools, restore level */
-                           _lock_release(&fp->lock);
-
-                           /* It's safe to do the following interruptible */
-                           if (zero)
-                               pageclr(o->address, many);
-                           pages = o;
-                           STAT(STAT_PAGES_ALLOC, many);
-                           goto end;
-                       }
-                   }
-               }
-           }
-
-           _lock_release(&fp->lock);
-       }
-       /* If we reach this point the allocation process desperatly failed */
-    }
-
-end:
-    if (pages == NULL) {
-       STAT(STAT_PAGES_ALLOC_NOMEM, 1);
-       DEBUG_PRINTF("- %T pages_alloc(%d, %u, %B) - Out of memory\n",
-               memtype, many, zero);
-    }
-
-    return pages;
-}
-
-
-/* Frees one or more contiguous pages of physical memory which were obtained
- * using pages_alloc(). It is important to call this function on the same
- * page_t pointer which was obtained from pages_alloc().
- */
-bool pages_free(page_t *pages)
-{
-    bool ok = FALSE;
-
-    if (pages != NULL && pages->last != NULL) {
-       register mchunk_t *m;
-       register page_t **idx, *fp, *lp, *lfp, *llp;
-       register u_int32_t id;
-
-       /* Find mchunk_t we belong to, setup variables */
-       fp = pages;
-       lp = pages->last;
-       m = pages->mchunk;
-       idx = m->index;
-
-       lock_acquire(&m->ppool->lock);
-
-       /* Reset pages fields. Because the freeing process requires running
-        * among pages looking for PS_FREE ones, we need to perform this
-        * while we own the lock.
-        */
-       for (lfp = fp; lfp != NULL; lfp = (page_t *)lfp->node.next)
-           lfp->state = PS_FREE;
-
-       /* Determine where in the free list_t of our mchunk_t should our page_t
-        * nodes be inserted. It is important that the free list always remain
-        * sorted. Using the page index ID of our first and last allocated
-        * pages, we can run up and down among pages to obtain this
-        * information. Another possible method would be to use a minheap
-        * implementation.
-        */
-       for (id = fp->id - 1; id > -1 && idx[id]->state != PS_FREE; id--) ;
-       if (id == -1 || idx[id]->state == PS_ALLOCATED)
-           lfp = NULL;
-       else
-           lfp = idx[id];
-       for (id = lp->id + 1; id < m->pages && idx[id]->state != PS_FREE;
-               id++) ;
-       if (id == m->pages || idx[id]->state == PS_ALLOCATED)
-           llp = NULL;
-       else
-           llp = idx[id];
-
-       /* Now lfp == free page_t to attach first page_t to (or NULL)
-        * and llp == free page_t to attach last page_t to (or NULL).
-        * We also know that within this mchunk_t no pages should exist
-        * between our first and last allocated pages because they are
-        * contiguous; We thus can safely insert our allocated pages in one
-        * efficient step between lfp and llp. We could have done the following
-        * immediately after checking for ID boundaries in the previous loops,
-        * but decide to perform NULL checking instead for code clarity.
-        * Link lfp (or top of list) to fp in both directions, and make sure
-        * to set the list top and bottom pointers when necessary as well.
-        */
-       if (lfp == NULL) {
-           m->free.top = (node_t *)fp;
-           fp->node.prev = NULL;
-       } else {
-           lfp->node.next = (node_t *)fp;
-           fp->node.prev = (node_t *)lfp;
-       }
-       /* Link llp (or bottom of list) to lp in both directions */
-       if (llp == NULL) {
-           m->free.bottom = (node_t *)lp;
-           lp->node.next = NULL;
-       } else {
-           llp->node.prev = (node_t *)lp;
-           lp->node.next = (node_t *)llp;
-       }
-       /* Fix number of free nodes counter */
-       m->free.nodes += (lp->id - fp->id) + 1;
-
-       _lock_release(&m->ppool->lock);
-
-       STAT(STAT_PAGES_FREE, (lp->id - fp->id) + 1);
-
-       /* Make sure to not agree to free these anymore until this page_t *
-        * is obtained again from pages_alloc(). As the page may have been
-        * part of a pool_t, we also must zero the pool pointer.
-        */
-       pages->last = NULL;
-       pages->pool = NULL;
-
-       ok = TRUE;
-    }
-
-    if (!ok) {
-       STAT(STAT_PAGES_FREE_FAILED, 1);
-       DEBUG_PRINTF("* %T pages_free(%p)\n", pages);
-    }
-
-    return ok;
-}
-
-
-/* Initializes a pool_t and allocates the required minimum pages if required.
- * The pages of a pool_t can be virtually sized as large as required by
- * specifying a steppages larger than 1. steppages * _PAGE_SIZE is the
- * actual size of a pool_t page. A pool can then be used to allocate objects
- * exceeding _PAGE_SIZE. No locking or synchronization is used by
- * pool_t functions, those must be provided externally by the caller if
- * needed. Of course internal page allocation/free will be done protected by
- * the system pages pool lock. A pool_t links the pages to it's lists via
- * the pages_t->poolnode node_t. If minpages == 0, no pages are allocated
- * until the first pool_alloc() is called on the pool_t. If maxpages == 0
- * the pool will always attempt to grow dynamically if required (and pnode_t
- * allocations will fail if out of memory). If minpages and maxpages are
- * non-zero and the same, pages are pre-allocated immediately and the pool
- * will never shrink or grow. This can be very useful in the case of critical
- * code sections which need to allocate and free objects in an interrupt
- * context. A pool_t, unlike an mpool_t, will not allow to specify which
- * memory type to allocate at each pnode_t allocation. It is however safe to
- * use _MEM_ANY for memtype here in which case any free memory will be used,
- * requested and freed as necessary.
- */
-bool pool_init(pool_t *pool, u_int32_t steppages, u_int32_t minpages,
-       u_int32_t maxpages, size_t nodesize, int memtype)
-{
-    bool ok = FALSE;
-
-    if (pool != NULL && steppages != 0 && nodesize >= sizeof(pnode_t) &&
-           memtype < (enum _memtypes)_MEM_MAX && memtype > -2) {
-       register size_t psize;
-       register u_int32_t nodesperpage, step = steppages;
-
-       /* Evaluate how many nodes can fit a page, and that it's realistic.
-        * There is no point in using a pool_t if we cannot fit at least two
-        * pnode_t objects per page_t. So we'll automatically increase
-        * steppages if needed here, upto 8 maximum, and return FALSE if
-        * we couln't reach a decent size relatively to the object size.
-        * The reason we're doing this is that Xisop system objects pools
-        * should grow steppages automatically if needed, and are always sure
-        * to be small enough to at least fit into 8 pages (usually 1-2).
-        * We want main.c's spools_init() to always succeed even if
-        * an object was slightly too large for a single page.
-        */
-       OBJECT_INVALIDATE(pool);
-       nodesize = (size_t)OALIGN_CEIL(nodesize, u_int32_t);
-       /* All your optimization are belong to us. */
-       for (psize = _PAGE_SIZE * step;
-               (nodesperpage = psize / nodesize) < 2 && step < 9;
-               psize = _PAGE_SIZE * (++step))
-           STAT(STAT_POOLS_ENLARGED, 1);
-       if (nodesperpage > 1) {
-           pool->nodesperpage = nodesperpage;
-           pool->steppages = step;
-           pool->minpages = minpages;
-           pool->maxpages = maxpages;
-           pool->avgtotal = pool->avgcnt = minpages;
-           pool->nodesize = nodesize;
-           pool->memtype = memtype;
-           DLIST_INIT(&pool->pages);
-           DLIST_INIT(&pool->fpages);
-           DLIST_INIT(&pool->nodes);
-           pool->mpool = NULL;
-           /* Allocate and initialize pages and nodes if needed */
-           for (; minpages > 0; minpages--) {
-               register page_t *p;
-
-               if ((p = pages_alloc(memtype, step, FALSE)) != NULL) {
-                   register u_int8_t *ptr, *toptr;
-
-                   /* pool_t pages are linked via page_t->poolnode */
-                   p->pnodes = nodesperpage;
-                   p->pool = pool;
-                   DLIST_APPEND(&pool->pages, &p->poolnode);
-                   for (ptr = (u_int8_t *)p->address, toptr = ptr + psize;
-                           ptr + nodesize < toptr;
-                           ptr += nodesize) {
-                       ((pnode_t *)ptr)->page = p;
-                       DLIST_APPEND(&pool->nodes, (node_t *)ptr);
-                   }
-               } else
-                   break;
-           }
-           OBJECT_VALIDATE(pool, OBJECT_POOL);
-           if (minpages == 0)
-               ok = TRUE;
-           else if (minpages < pool->minpages) {
-               /* Some of minpages were allocated, we need to free them */
-               pool_destroy(pool);
-               DEBUG_PRINTF(
-                   "* %T pool_init(%p, %u, %u, %u, %u, %d) - Out of memory\n",
-                   pool, steppages, minpages, maxpages, nodesize, memtype);
-           }
-       }
-    }
-
-    if (ok)
-       STAT(STAT_POOLS_CREATED, 1);
-    else {
-       STAT(STAT_POOLS_CREATED_FAILED, 1);
-       DEBUG_PRINTF("* %T pool_init(%p, %u, %u, %u, %u, %d)\n",
-               pool, steppages, minpages, maxpages, nodesize, memtype);
-    }
-
-    return ok;
-}
-
-
-/* Frees all memory allocated by a pool_t, thus rendering any allocated
- * pnode_t objects invalid as well. The pool_t is then marked as invalid,
- * it can only be valid again if initialized using pool_init().
- * FALSE is returned if the pool_t is invalidated already.
- */
-bool pool_destroy(pool_t *pool)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(pool, OBJECT_POOL)) {
-       register node_t *p, *t;
-
-       /* Just free all pages allocated by the pool, and mark the pool
-        * as freed/nonfunctional. All nodes on the list will be reset if
-        * a new pool is initialized using this pool_t *. They become
-        * invalid as soon as pages are freed, since they only consist of
-        * pointers into those pages. Remember that pool pages are tied
-        * up in the list_t via the page_t->poolnode node_t.
-        */
-       for (p = DLIST_TOP(&pool->pages); p != NULL; p = t) {
-           t = DLIST_NEXT(p);
-           pages_free((page_t *)(--p));
-       }
-       for (p = DLIST_TOP(&pool->fpages); p != NULL; p = t) {
-           t = DLIST_NEXT(p);
-           pages_free((page_t *)(--p));
-       }
-       OBJECT_INVALIDATE(pool);
-       ok = TRUE;
-    }
-
-    if (ok)
-       STAT(STAT_POOLS_DESTROYED, 1);
-    else {
-       STAT(STAT_POOLS_DESTROYED_FAILED, 1);
-       DEBUG_PRINTF("* %T pool_destroy(%p)\n", pool);
-    }
-
-    return ok;
-}
-
-
-/* Attempts to allocate a pnode_t from the specified pool_t, and optionally
- * clear the object to 0x00 bytes if zero is TRUE. NULL is returned if
- * no memory was available or if the pool was setup to not be able to hold
- * more objects. The size of the pnode_t prefixed object depends on the
- * attributes which were set forthe pool_t at pool_init(). As each node
- * object should start with a pnode_t structure, we return a pointer to
- * the object structure itself at the same time. The type of memory used
- * can only be the one the pool_t was initialized for. The pnode_t allocation
- * process is efficient, compared to managing page_t. Special care is taken
- * to avoid calling page primitives as much as possible using buffering,
- * while still allowing a pool_t to be dynamically resizing if wanted.
- */
-pnode_t *pool_alloc(pool_t *pool, bool zero)
-{
-    pnode_t *pnode = NULL;
-
-    if (OBJECT_VALID(pool, OBJECT_POOL)) {
-       register pnode_t *pn;
-
-       /* If there are pre-buffered nodes, simply return the first one. */
-       if ((pn = DLIST_TOP(&pool->nodes)) != NULL) {
-           DLIST_UNLINK(&pool->nodes, (node_t *)pn);
-           pn->page->pnodes--;
-           if (zero) {
-               register page_t *p;
-
-               p = pn->page;
-               memclr(pn, pool->nodesize);
-               pn->page = p;
-           }
-           pnode = pn;
-       } else {
-           register page_t *p = NULL;
-           register node_t *n;
-
-           /* No pnode_t left, we need to allocate a new page_t to grow and
-            * initialize the new bnode_t objects. First verify if there is
-            * any available page already in our cache, which pool_free()
-            * maintains using statistics, to minimize calls to page
-            * primitives functions. If there are none, allocate a new page_t.
-            * Remember that we link the pages via the page_t->poolnode node_t.
-            */
-           if (pool->maxpages == 0 ||
-                   DLIST_NODES(&pool->pages) < pool->maxpages) {
-               if ((n = DLIST_TOP(&pool->fpages)) != NULL) {
-                   DLIST_UNLINK(&pool->fpages, n);
-                   p = (page_t *)(--n);
-                   STAT(STAT_PAGES_REUSED, pool->steppages);
-               } else
-                   p = pages_alloc(pool->memtype, pool->steppages, FALSE);
-               if (p != NULL) {
-                   register u_int8_t *ptr, *toptr;
-                   register size_t nodesize = pool->nodesize;
-
-                   p->pnodes = pool->nodesperpage;
-                   p->pool = pool;
-                   DLIST_APPEND(&pool->pages, &p->poolnode);
-                   for (ptr = (u_int8_t *)p->address,
-                           toptr = ptr + _PAGE_SIZE * pool->steppages;
-                           ptr + nodesize < toptr;
-                           ptr += nodesize) {
-                       ((pnode_t *)ptr)->page = p;
-                       DLIST_APPEND(&pool->nodes, (node_t *)ptr);
-                   }
-                   /* Now grab first pnode_t */
-                   pn = DLIST_TOP(&pool->nodes);
-                   DLIST_UNLINK(&pool->nodes, (node_t *)pn);
-                   p->pnodes--;
-                   if (zero)
-                       memclr(pn, nodesize);
-                   pn->page = p;
-                   pnode = pn;
-               }
-           } else {
-               STAT(STAT_POOLS_ALLOC_NOMEM, 1);
-               DEBUG_PRINTF("- %T pool_alloc(%p, %B) - Out of memory\n",
-                       pool, zero);
-           }
-       }
-    } else {
-       STAT(STAT_POOLS_ALLOC_FAILED, 1);
-       DEBUG_PRINTF("* %T pool_alloc(%p, %B)\n", pool, zero);
-    }
-
-    if (pnode != NULL)
-       STAT(STAT_POOLS_ALLOC, 1);
-
-    return pnode;
-}
-
-
-/* Used to free a node previously allocated using pool_alloc().
- * Keeps statistics and a page cache to reduce the frequency at which
- * pages_*() functions need to be called.
- */
-pnode_t *pool_free(pnode_t *pnode)
-{
-    if (pnode != NULL && OBJECT_VALID(pnode->page->pool, OBJECT_POOL)) {
-       register page_t *p = pnode->page;
-       register pool_t *pool = p->pool;
-       register u_int32_t exceeding;
-
-       /* Efficiently return this node in the free list */
-       DLIST_INSERT(&pool->nodes, (node_t *)pnode);
-       p->pnodes++;
-       STAT(STAT_POOLS_FREE, 1);
-       if ((pool->minpages < pool->maxpages) ||
-               (pool->minpages == 0 && pool->maxpages == 0)) {
-           register u_int32_t pages = DLIST_NODES(&pool->pages);
-
-           /* This is a pool_t which can shrink, book-keep statistics on
-            * average pages usage.
-            */
-           pool->avgtotal += pages;
-           pool->avgcnt++;
-           if (pool->avgcnt >
-                   ((pool->steppages * _PAGE_SIZE / pool->nodesize) * 3)) {
-               pool->avgcnt = 1;
-               pool->avgtotal = pages;
-           }
-
-           if (p->pnodes == pool->nodesperpage && pool->minpages < pages) {
-               register u_int8_t *ptr, *toptr;
-               register size_t nodesize;
-
-               /* All pnode_t objects belonging to this page_t were freed.
-                * Swap the page to the cache to be freed. We also need
-                * to sequencially unlink all the pnode_t objects this page
-                * supplied in the free nodes list_t. Remember that pages
-                * are linked via the page_t->poolnode node_t.
-                */
-               for (ptr = (u_int8_t *)p->address,
-                       toptr = ptr + _PAGE_SIZE * pool->steppages,
-                       nodesize = pool->nodesize;
-                       ptr + nodesize < toptr;
-                       ptr += nodesize)
-                   DLIST_UNLINK(&pool->nodes, (node_t *)ptr);
-               /* Insert to preferably reuse recently used pages */
-               DLIST_SWAP(&pool->fpages, &pool->pages, &(p->poolnode), TRUE);
-               STAT(STAT_PAGES_BUFFERED, pool->steppages);
-           }
-
-           /* Do statistics suggest that we should shrink the pool? If so,
-            * free pages from our cache back to the system.
-            */
-           if ((exceeding = (DLIST_NODES(&pool->pages) +
-                           DLIST_NODES(&pool->fpages)) -
-                       (pool->avgtotal / pool->avgcnt)) > 0) {
-               register list_t *fpages = &pool->fpages;
-               register node_t *n;
-
-               /* Preferably free pages which haven't been used recently */
-               for (; exceeding > 0 && (n = fpages->bottom) != NULL;
-                       exceeding--) {
-                   DLIST_UNLINK(fpages, n);
-                   p = (page_t *)(--n);
-                   pages_free(p);
-                   STAT(STAT_PAGES_UNBUFFERED, pool->steppages);
-               }
-           }
-       }
-    } else {
-       STAT(STAT_POOLS_FREE_FAILED, 1);
-       DEBUG_PRINTF("* %T pool_free(%p)\n", pnode);
-    }
-
-    return NULL;
-}
-
-
-/* Finally, the higher-level general purpose allocation system consists of
- * a bunch of pool_t, as well as a page_t list_t for requests which exceed
- * in size and need to be rounded at page boundaries. Memory of all available
- * types may be allocated and freed at will, and of arbitrary sized blocks.
- * The current implementation requires more memory for mpool setup than
- * previously, there however are advantages in versatility, performance
- * and code quality over the latter.
- * We depend on _PAGE_SIZE and _MPOOLS which should be defined by the
- * port-specific code (port/support.h).
- * No special synchronization is performed in these functions, the caller
- * is required to provide it where necessary (i.e. shared mpool_t). However,
- * the underlaying page_t primitives use the system pages pool lock.
- */
-bool mpool_init(mpool_t *mpool)
-{
-    bool ok = FALSE;
-
-    if (mpool != NULL) {
-       register int t, p;
-       register size_t c = _MPOOLSTART;
-
-       DLIST_INIT(&mpool->pages);
-       ok = TRUE;
-       OBJECT_VALIDATE(mpool, OBJECT_MPOOL);
-       for (p = 0; p < _MPOOLS; p++) {
-           for (t = 0; t < (enum _memtypes)_MEM_MAX; t++) {
-               if (!pool_init(&mpool->pools[p][t], _MPOOLSTEP, 0, 0,
-                           sizeof(mnode_t) + c, t))
-                   ok = FALSE;
-               else
-                   mpool->pools[p][t].mpool = mpool;
-           }
-           c *= 2;
-       }
-       if (!ok) {
-           /* Make sure to free everything if part of the system only could be
-            * setup
-            */
-           mpool_destroy(mpool);
-       } else {
-           mpool->shared = FALSE;
-           _lock_init(&mpool->lock);
-           mpool->usecount = 0;
-       }
-    }
-
-    if (ok)
-       STAT(STAT_MPOOLS_CREATED, 1);
-    else {
-       STAT(STAT_MPOOLS_CREATED_FAILED, 1);
-       DEBUG_PRINTF("* %T mpool_init(%p)\n", mpool);
-    }
-
-    return ok;
-}
-
-
-bool mpool_destroy(mpool_t *mpool)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(mpool, OBJECT_MPOOL)) {
-       register int t, p;
-       register node_t *pg, *tmp;
-       register u_int32_t usecount = 0;
-
-       if (mpool->shared) {
-           lock_acquire(&mpool->lock);
-           usecount = --mpool->usecount;
-           _lock_release(&mpool->lock);
-       }
-       if (usecount < 1) {
-           /* All your pool_t are belong to us. */
-           for (p = 0; p < _MPOOLS; p++)
-               for (t = 0; t < (enum _memtypes)_MEM_MAX; t++)
-                   pool_destroy(&mpool->pools[p][t]);
-           /* And rounded page requests too. Remember that they are tied via
-            * the page_t->poolnode node_t in our list_t.
-            */
-           for (pg = DLIST_TOP(&mpool->pages); pg != NULL; pg = tmp) {
-               tmp = DLIST_NEXT(pg);
-               pages_free((page_t *)(--pg));
-           }
-           OBJECT_INVALIDATE(mpool);
-           ok = TRUE;
-           STAT(STAT_MPOOLS_DESTROYED, 1);
-       }
-    } else {
-       STAT(STAT_MPOOLS_DESTROYED_FAILED, 1);
-       DEBUG_PRINTF("* %T mpool_destroy(%p)\n", mpool);
-    }
-
-    return ok;
-}
-
-
-/* malloc() clone which can be specified mpool_t to use, memory type
- * and optional memory clear flag.
- */
-void *_malloc(mpool_t *mpool, int memtype, size_t size, bool zero)
-{
-    void *mem = NULL;
-
-    if (OBJECT_VALID(mpool, OBJECT_MPOOL) &&
-           (memtype == _MEM_ANY || memtype < (enum _memtypes)_MEM_MAX)) {
-       register int p;
-       register size_t rsize;
-
-       /* Synchronization for cases where multiple tasks share an mpool_t */
-       if (mpool->shared)
-           lock_acquire(&mpool->lock);
-
-       /* Verify if any of our pool_t can serve the requested size */
-       rsize = (size_t)OALIGN_CEIL(sizeof(mnode_t), u_int32_t);
-       rsize += size;
-       for (p = 0; p < _MPOOLS; p++) {
-           if (mpool->pools[p][0].nodesize >= rsize) {
-               register mnode_t *n = NULL;
-
-               /* This pool can serve this request. */
-               if (memtype == _MEM_ANY) {
-                   register int t;
-
-                   /* Try available memory types in order */
-                   for (t = 0; t < (enum _memtypes)_MEM_MAX; t++) {
-                       n = (mnode_t *)pool_alloc(&mpool->pools[p][t], zero);
-                       if (n != NULL)
-                           break;
-                   }
-               } else
-                   n = (mnode_t *)pool_alloc(&mpool->pools[p][memtype], zero);
-               if (n != NULL) {
-                   /* Best case, everything went fine */
-                   n->type = MNT_PNODE;
-                   OBJECT_VALIDATE(n, OBJECT_MNODE);
-                   mem = (++n);
-                   break;
-               } else {
-                   STAT(STAT_MPOOLS_ALLOC_NOMEM, 1);
-                   DEBUG_PRINTF(
-                           "- %T _malloc(%p, %d, %u, %B) - Out of memory\n",
-                           mpool, memtype, size, zero);
-               }
-           }
-       }
-       if (p == _MPOOLS) {
-           register u_int32_t many;
-           register page_t *p;
-
-           /* We need to round size on page boundaries and allocate pages.
-            * If we were requested zeroed memory, the pageclr() will be used
-            * internally which is more efficient than memclr().
-            */
-           many = rsize / _PAGE_SIZE;
-           if (rsize % _PAGE_SIZE)
-               many++;
-           if ((p = pages_alloc(memtype, many, zero)) != NULL) {
-               register mnode_t *n = p->address;
-
-               /* Link in our pages list via the page_t->poolnode node_t */
-               DLIST_APPEND(&mpool->pages, &p->poolnode);
-               n->u.pgnode.pages = p;
-               n->u.pgnode.mpool = mpool;
-               n->type = MNT_PAGES;
-               OBJECT_VALIDATE(n, OBJECT_MNODE);
-               mem = (++n);
-           } else {
-               STAT(STAT_MPOOLS_ALLOC_NOMEM, 1);
-               DEBUG_PRINTF("- %T _malloc(%p, %d, %u, %B) - Out of memory\n",
-                       mpool, memtype, size, zero);
-           }
-       }
-
-       if (mpool->shared)
-           _lock_release(&mpool->lock);
-    } else {
-       STAT(STAT_MPOOLS_ALLOC_FAILED, 1);
-       DEBUG_PRINTF("* %T _malloc(%p, %d, %u, %B)\n",
-               mpool, memtype, size, zero);
-    }
-
-    if (mem != NULL)
-       STAT(STAT_MPOOLS_ALLOC, 1);
-
-    return mem;
-}
-
-
-/* free() clone for _malloc() */
-void *_free(void *block)
-{
-    register mpool_t *mpool = NULL;
-
-    if (block != NULL) {
-       register mnode_t *mn = block;
-
-       mn--;
-       if (OBJECT_VALID(mn, OBJECT_MNODE)) {
-
-           OBJECT_INVALIDATE(mn);
-           switch (mn->type) {
-           case MNT_PNODE:
-               /* A pool_t pnode_t which needs to be freed back. Track our
-                * mpool_t for synchronization if required.
-                */
-               if ((mpool = mn->u.pnode.page->pool->mpool) != NULL) {
-                   if (mpool->shared)
-                       lock_acquire(&mpool->lock);
-                   else
-                       mpool = NULL;
-               }
-               pool_free((pnode_t *)mn);
-               break;
-           case MNT_PAGES:
-               {
-                   register page_t *p = mn->u.pgnode.pages;
-
-                   /* A page_t which needs to be unlinked and freed.
-                    * Remember that pages are linked via page_t->poolnode
-                    * node_t. Track our mpool_t for synchronization if needed.
-                    */
-                   mpool = mn->u.pgnode.mpool;
-                   if (mpool->shared)
-                       lock_acquire(&mpool->lock);
-                   else
-                       mpool = NULL;
-                   DLIST_UNLINK(&mn->u.pgnode.mpool->pages, &p->poolnode);
-                   pages_free(p);
-                   break;
-               }
-           }
-           STAT(STAT_MPOOLS_FREE, 1);
-       } else {
-           STAT(STAT_MPOOLS_FREE_FAILED, 1);
-           DEBUG_PRINTF("* %T _free(%p)\n", block);
-       }
-    } else {
-       STAT(STAT_MPOOLS_FREE_FAILED, 1);
-       DEBUG_PRINTF("* %T _free(%p)\n", block);
-    }
-    if (mpool != NULL)
-       _lock_release(&mpool->lock);
-
-    return NULL;
-}
-
-
-
-/* This function initializes the various pool_t and _lock_t which are reserved
- * to allocate specific types of Xisop system objects for efficiency.
- */
-void spools_init(void)
-{
-    register int i;
-
-    /* XXX Should panic on failure */
-    for (i = 0; i < (enum _syspools)POOL_MAX; i++) {
-       _lock_init(&root->spools_locks[i]);
-       (void) pool_init(&root->spools[i], syspools_params[i].steppages,
-                        syspools_params[i].minpages,
-                        syspools_params[i].maxpages,
-                        syspools_params[i].nodesize, 0);
-    }
-}
-
-
-pnode_t *spool_alloc(u_int32_t pool)
-{
-    pnode_t *node = NULL;
-
-    if (pool < (enum _syspools)POOL_MAX) {
-       lock_acquire(&root->spools_locks[pool]);
-       node = pool_alloc(&root->spools[pool], FALSE);
-       _lock_release(&root->spools_locks[pool]);
-    }
-
-    if (node == NULL)
-       DEBUG_PRINTF("* %T spool_alloc(%u)\n", pool);
-
-    return node;
-}
-
-
-pnode_t *spool_free(u_int32_t pool, pnode_t *node)
-{
-    if (pool < (enum _syspools)POOL_MAX) {
-       lock_acquire(&root->spools_locks[pool]);
-       if (!pool_free(node))
-           DEBUG_PRINTF("* %T spool_free(%u, %p)\n", pool, node);
-       _lock_release(&root->spools_locks[pool]);
-    }
-
-    return NULL;
-}
-
-
-/* Specifically made to allocate general purpose memory for the kernel.
- * Although mpool_t now can support synchronization itself when shared,
- * it is faster to perform it unconditionally.
- */
-void *_kmalloc(int memtype, size_t size, bool zero)
-{
-    void *mem = NULL;
-
-    lock_acquire(&root->kernpool_lock);
-    mem = _malloc(root->kernpool, memtype, size, zero);
-    _lock_release(&root->kernpool_lock);
-
-    return mem;
-}
-
-void *_kfree(void *mem)
-{
-    lock_acquire(&root->kernpool_lock);
-    _free(mem);
-    _lock_release(&root->kernpool_lock);
-
-    return NULL;
-}
-
-
-/* Closer to ANSI-C but still for general purpose kernel memory */
-void *kmalloc(size_t size)
-{
-    return MALLOC(size);
-}
-
-void kfree(void *mem)
-{
-    FREE(mem);
-}
-
-
-/* These functions are ANSI-C standard, and only use the current task pool. */
-
-void *malloc(size_t size)
-{
-    return _malloc(CURTASK()->mpool, _MEM_ANY, size, FALSE);
-}
-
-void *calloc(int number, size_t size)
-{
-    return _malloc(CURTASK()->mpool, _MEM_ANY, number * size, TRUE);
-}
-
-void *realloc(void *ptr, size_t size)
-{
-    register void *nptr = ptr;
-
-    /* Not very efficient, but mostly provided for compatibility. */
-    if (nptr != NULL) {
-       if (size == 0)
-           /* Basically a request to free the buffer */
-           nptr = _free(nptr);
-       else {
-           register mnode_t *mnode;
-
-           /* Climb up to obtain actual buffer size */
-           mnode = (mnode_t *)nptr;
-           mnode--;
-           if (OBJECT_VALID(mnode, OBJECT_MNODE)) {
-               register size_t osize;
-
-               switch (mnode->type) {
-               case MNT_PNODE:
-                   {
-                       osize = mnode->u.pnode.page->pool->nodesize -
-                           sizeof(mnode_t);
-                       break;
-                   }
-               case MNT_PAGES:
-                   {
-                       register page_t *pages = mnode->u.pgnode.pages;
-
-                       osize = ((pages->last->id - pages->id) +1) *
-                           _PAGE_SIZE;
-                       break;
-                   }
-               default:
-                   nptr = NULL;
-                   osize = 0;
-                   break;
-               }
-
-               /* Is the requested size larger than the currently available
-                * number of bytes? If not, don't do anything, return the
-                * current buffer pointer.
-                */
-               if (nptr != NULL && osize < size) {
-                   /* Allocate a buffer which can at least hold the requested
-                    * number of bytes. Well at least, attempt to. If we can't
-                    * don't do anything and return NULL.
-                    */
-                   if ((nptr = malloc(size)) != NULL) {
-                       /* Allocation successful, copy all previous buffer
-                        * contents to the new one, then free the old buffer,
-                        * and return the new buffer pointer.
-                        */
-                       memcpy(nptr, ptr, osize);
-                       free(ptr);
-                   }
-               }
-           } else
-               nptr = NULL;
-       }
-    } else
-       /* A request to simply allocate */
-       nptr = malloc(size);
-
-    return nptr;
-}
-
-void free(void *ptr)
-{
-    _free(ptr);
-}
-
-
-/* Xisop extentions as we support multiple memory types */
-void *tmalloc(int memtype, size_t size)
-{
-    return _malloc(CURTASK()->mpool, memtype, size, FALSE);
-}
-
-void *tcmalloc(int memtype, int number, size_t size)
-{
-    return _malloc(CURTASK()->mpool, memtype, number * size, TRUE);
-}
-
-
-
-/* The following code is only compiled in if DEBUG was #defined in config.h */
-#ifdef DEBUG
-
-
-/* Dump the current state of all memory pages in the system. */
-void pages_dump(void)
-{
-    register u_int32_t ppool;
-    _ipl_t x;
-
-    /* Become absolutely uninterruptible */
-    x = _splhigh();
-
-    debug_printf("\nCURRENT STATE OF SYSTEM MEMORY PAGES\n");
-    for (ppool = 0; ppool < (enum _memtypes)_MEM_MAX; ppool++) {
-       register mchunk_t *mchunk;
-
-       debug_printf("\nDumping mchunks for ppool_t of _MEM_TYPE %u\n",
-               ppool);
-       DLIST_FOREACH(&(root->ppools[ppool].mchunks), mchunk) {
-           register page_t **index = mchunk->index;
-           register u_int32_t id, pages = mchunk->pages;
-
-           debug_printf(
-               " Dumping pages for mchunk_t *%p (%u pages, page_t **%p)\n",
-                   mchunk, pages, index);
-           debug_printf(" mchunk->free.top = ");
-           if (mchunk->free.top != NULL)
-               debug_printf(
-                       "%u (page_t *%p)\n", ((page_t *)mchunk->free.top)->id,
-                       mchunk->free.top);
-           else
-               debug_printf("NULL\n");
-           debug_printf(" mchunk->free.bottom = ");
-           if (mchunk->free.bottom != NULL)
-               debug_printf("%u (page_t *%p)\n",
-                       ((page_t *)mchunk->free.bottom)->id,
-                       mchunk->free.bottom);
-           else
-               debug_printf("NULL\n");
-           for (id = 0; id < pages; id++) {
-               register page_t *page = index[id];
-
-               /* Print summary information */
-               debug_printf(" - %u (page_t *%p, void *%p)\n   next = ",
-                       id, page, page->address);
-               if (page->node.next == NULL)
-                   debug_printf("NULL, prev = ");
-               else
-                   debug_printf("%u (page_t *%p), prev = ",
-                           ((page_t *)page->node.next)->id,
-                           page->node.next);
-               if (page->node.prev == NULL)
-                   debug_printf("NULL\n");
-               else
-                   debug_printf("%u (page_t *%p)\n",
-                           ((page_t *)page->node.prev)->id,
-                           page->node.prev);
-
-               /* Rest will vary depending if page is allocated */
-               if(page->state == PS_ALLOCATED) {
-                   debug_printf("   Allocated, last = ");
-                   if (page->last != NULL)
-                       debug_printf("%u (page_t *%p)\n", page->last->id,
-                               page->last);
-                   else
-                       debug_printf("NULL\n");
-                   if (page->pool != NULL)
-                       debug_printf("   pool_t = *%p, mem %d, nodesize %u\n",
-                               page->pool, page->pool->memtype,
-                               page->pool->nodesize);
-               } else
-                   debug_printf("   Free\n");
-
-               /* Perform some basic sanity checking and report problems
-                * which are known to disrupt the system. If those occur,
-                * the pools were corrupted and the system may need a reset
-                * for proper operation.
-                */
-               if (page->node.next != NULL) {
-                   register node_t *n = page->node.next;
-
-                   if (n->prev == NULL)
-                       debug_printf(
-                               "   * page->node.next->node.prev = NULL\n");
-                   else if (n->prev != &page->node)
-                       debug_printf(
-                               "   * page->node.next->node.prev != page\n");
-               }
-               if (page->node.prev != NULL) {
-                   register node_t *n = page->node.prev;
-
-                   if (n->next == NULL)
-                       debug_printf(
-                               "   * page->node.prev->node.next = NULL\n");
-                   else if (n->next != &page->node)
-                       debug_printf(
-                               "   * page->node.prev->node.next != page\n");
-               }
-               if (page->id != id)
-                   debug_printf("   * page->id != index[id]\n");
-               if (page->state != PS_FREE && page->state != PS_ALLOCATED)
-                   debug_printf("   * Unknown page->state\n");
-               if (page->state == PS_FREE && page->last != NULL)
-                   debug_printf("   * PS_FREE && last != NULL\n");
-               if (page->state == PS_FREE && page->pool != NULL)
-                   debug_printf("   * PS_FREE && page->pool != NULL");
-               if (page->mchunk != mchunk)
-                   debug_printf("   * page->mchunk != mchunk\n");
-           }
-       }
-    }
-
-    _splx(x);
-}
-
-
-#endif
diff --git a/Xisop/src/common/kernel/memory.h b/Xisop/src/common/kernel/memory.h
deleted file mode 100644 (file)
index 146d7b8..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/* $Id: memory.h,v 1.4 2004/06/04 03:09:48 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNEL_MEMORY_H
-#define KERNEL_MEMORY_H
-
-
-
-#include <common/types.h>
-#include <common/kernlib/list.h>
-#include <processor/support.h>
-#include <port/support.h>
-
-
-
-/* Only common memory type which is always available */
-#define _MEM_ANY               -1
-
-/* Page state */
-#define PS_FREE                        0
-#define PS_ALLOCATED           1
-
-/* mnode_t types */
-#define MNT_PNODE              0
-#define MNT_PAGES              1
-
-
-
-/* This is a memory page node. One is required for each physical page which
- * is to be included in the memory management system. The pool_t related
- * fields seem to pollute the page space, but there is no better place to put
- * them; Using an additional page_t based structure for pool_t page_t nodes
- * would require allocating more memory. The pool_t primitives are such a
- * vital element to Xisop that we can add support for it inherently.
- */
-struct page {
-    node_t node;       /* Link to pages_free of mchunk or pages_t */
-    node_t poolnode;   /* Used for pool_t page linking */
-    mchunk_t *mchunk;  /* mchunk_t we belong to for freeing */
-    void *address;     /* Page address in memory (should be 32-bit aligned) */
-    page_t *last;      /* Allocated? Link to last contiguous node, or NULL */
-    pool_t *pool;      /* If part of a pool_t, pointer to the pool_t */
-    u_int32_t id;      /* Page index offset in mchunk_t */
-    u_int32_t pnodes;  /* Number of free blocks in this page_t for pool_t */
-    u_int32_t state;   /* PS_FREE | PS_ALLOCATED */
-};
-
-/* A chunk of memory consists of an arbitrary amount of contiguous pages
- * of physical memory. This construct allows to dynamically append memory
- * which can be mapped anytime, i.e. PCMCIA memory which just was inserted.
- * Obviously, to add new memory some memory is required to be setup for the
- * lists, index and page nodes. This memory should never be freed back unless
- * it is certain that the device was detached, and all allocated memory on it
- * is to be discarded. Each such chunk will be scanned in order for available
- * memory when memory is to be allocated from a ppool_t.
- */
-struct mchunk {
-    node_t node;       /* Link to mpool_t */
-    list_t free;       /* List of free pages */
-    ppool_t *ppool;    /* Link to ppool_t we belong to */
-    page_t **index;    /* Index of all pages in this mchunk_t */
-    u_int32_t pages;   /* Number of pages in this mchunk_t */
-    u_int32_t object_magic;    /* Validity sceal */
-};
-
-/* A pool of pages, there is one such pool per memory type. These are
- * initialized by the port-specific _init_memory() function.
- */
-struct ppool {
-    _lock_t lock;      /* Secure exclusive access lock */
-    list_t mchunks;    /* List of mchunk_t objects */
-};
-
-
-
-/* A pool used to allocate objects of a fixed size, which are smaller than
- * half a page. maxpages permits to restrict the pool from growing more than
- * wanted, minpages specifies the minimum number of pages which should always
- * remain allocated (and setup as objects), avgtotal and avgcnt are used for
- * statistics when freeing pages (and destroying their objects). An unused
- * page is moved to fpages list, and moved back in pages list when an object
- * on the page is used. If statistics show that the pool should shrink, pages
- * from fpages are freed back to the system (unless minpages is reached).
- * steppages specify how many pages to allocate and free at once. A page size
- * for the pool consists of steppages * _PAGE_SIZE. All pool objects always
- * start by a node_t, used for internal linking when freed, and can be used
- * for custom linking after allocation until freed back.
- */
-struct pool {
-    u_int32_t steppages, minpages,     /* Size requirements */
-       maxpages;
-    u_int32_t avgtotal, avgcnt;                /* Statistics for page_t cache */
-    u_int32_t nodesperpage;            /* Number of pnode_t per page_t */
-    size_t nodesize;                   /* 32-bit aligned size of pnode_t */
-    list_t pages, fpages,              /* Allocated and cached page_t's */
-       nodes;                          /* Ready free pnode_t's */
-    int memtype;                       /* Memory type to allocate */
-    u_int32_t object_magic;            /* Validity sceal */
-    mpool_t *mpool;                    /* mpool_t we belong to (or NULL) */
-};
-
-/* A pool_t node */
-struct pnode {
-    node_t node;               /* pool_t->nodes or user list_t linking */
-    page_t *page;              /* page_t this pnode_t belongs to */
-};
-
-
-
-/* And finally, the general purpose memory management functions, allowing
- * blocks of memory of arbitrary size and type to be allocated and freed back,
- * internally based upon the pool_t system.
- */
-struct mpool {
-    /* All required pool_t for the various memory types and request sizes */
-    pool_t pools[_MPOOLS][(enum _memtypes)_MEM_MAX];
-    list_t pages;              /* Large requests rounded on page boundaries */
-    u_int32_t object_magic;    /* Validity sceal */
-    /* These are used in the case where several tasks share a common mpool_t,
-     * In which case the mpool_t is synchronized and only destroyed when no
-     * more tasks are using it. Because Xisop does not support MMU the
-     * requirement for this is questionable. Especially that through the
-     * message passing system tasks can easily synchronize on wanted shared
-     * memory regions. It can however save some memory on very small systems.
-     * All tasks could potentially share the same mpool_t if the init task
-     * was setup to do so, for instance.
-     */
-    bool shared;
-    _lock_t lock;
-    u_int32_t usecount;
-};
-
-/* An mpool_t node, which prefixes all allocated blocks, the ones from pools
- * as well as the ones made of rounded pages (which were too large to satisfy
- * using the pool_t objects). Contrary to pool_*() and pages_*() functions, the
- * mnode_t is abstracted and hidden in the supplied data block. The pointer
- * supplied to the caller points immediately after this structure
- * (32-bit aligned). We use a union to reduce as much as possible the size
- * of the structure, and be able to reference back to both pnode_t or
- * page_t + mpool_t objects.
- */
-struct mnode {
-    union {
-       pnode_t pnode;          /* We're a pnode_t */
-       struct {
-           page_t *pages;      /* We're a page_t from mpool_t */
-           mpool_t *mpool;
-       } pgnode;
-    } u;
-    int type;                  /* MNT_PAGES || MNT_PNODE */
-    u_int32_t object_magic;    /* Validity sceal */
-};
-
-
-
-/* The pool_t types Xisop initializes for efficient management of common
- * system objects. These should correspond to the osize structure defined in
- * memory.c's spools_init() function.
- */
-enum _syspools {
-    POOL_TASK = 0,
-    POOL_PORT,
-    POOL_DEVICENODE,
-    POOL_DEVICEHANDLE,
-    POOL_MPOOL,
-    POOL_MAX
-};
-
-/* An array of these is filled in memory.c for pools initialization */
-struct syspools_params {
-    const char *label;
-    u_int32_t steppages, minpages, maxpages;
-    size_t nodesize;
-};
-
-
-
-/* Useful macros intended to be used by kernel code */
-#define TMALLOC(t, s)          _kmalloc((t), (s), FALSE)
-#define TCMALLOC(t, n, s)      _kmalloc((t), (n) * (s), TRUE)
-#define MALLOC(s)              _kmalloc(_MEM_ANY, (s), FALSE)
-#define CMALLOC(n, s)          _kmalloc(_MEM_ANY, (n) * (s), TRUE)
-#define FREE(p)                        _kfree((p))
-
-
-
-void memory_init(void);
-
-void spools_init(void);
-pnode_t *spool_alloc(u_int32_t);
-pnode_t *spool_free(u_int32_t, pnode_t *);
-
-mchunk_t *mchunk_init(void *, size_t);
-bool mchunk_attach(int, mchunk_t *);
-bool mchunk_detach(int, mchunk_t *);
-
-page_t *pages_alloc(int, u_int32_t, bool);
-bool pages_free(page_t *);
-
-bool pool_init(pool_t *, u_int32_t, u_int32_t, u_int32_t, size_t, int);
-bool pool_destroy(pool_t *);
-pnode_t *pool_alloc(pool_t *, bool);
-pnode_t *pool_free(pnode_t *);
-
-bool mpool_init(mpool_t *);
-bool mpool_destroy(mpool_t *);
-void *_malloc(mpool_t *, int, size_t, bool);
-void *_free(void *);
-#define mpool_alloc _malloc
-#define mpool_free _free
-
-void *_kmalloc(int, size_t, bool);
-void *_kfree(void *);
-void *kmalloc(size_t);
-void kfree(void *);
-
-void *malloc(size_t);
-void *calloc(int, size_t);
-void *realloc(void *, size_t);
-void free(void *);
-void *tmalloc(int, size_t);
-void *tcmalloc(int, int, size_t);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/object.h b/Xisop/src/common/kernel/object.h
deleted file mode 100644 (file)
index f9a3e23..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* $Id: object.h,v 1.4 2004/06/04 19:03:36 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* For a good example of code which uses these, look at port.c's port_create(),
- * port_reply() and port_destroy() functions.
- */
-
-
-
-#ifndef COMMON_KERNEL_OBJECT_H
-#define COMMON_KERNEL_OBJECT_H
-
-
-
-#include <common/kernel/main.h>
-
-
-
-/* These should be unique and quite uncommon to happen randomly */
-#define OBJECT_PORT            0x504f5254      /* PORT */
-#define        OBJECT_TASK             0x5441534b      /* TASK */
-#define OBJECT_POOL            0x504f4f4c      /* POOL */
-#define OBJECT_MPOOL           0x4d504f4c      /* MPOL */
-#define OBJECT_MNODE           0x4d4e4f44      /* MNOD */
-#define OBJECT_MCHUNK          0x4d43484b      /* MCHK */
-#define OBJECT_DEVICEHANDLE    0x44455648      /* DEVH */
-#define OBJECT_DEVICENODE      0x4445564e      /* DEVN */
-#define OBJECT_IOREQUEST       0x494f5251      /* IORQ */
-#define OBJECT_HASHTABLE       0x4854424c      /* HTBL */
-#define OBJECT_HASHNODE                0x484e4f44      /* HNOD */
-
-
-
-/* Validate an object */
-#define OBJECT_VALIDATE(o, m)  (o)->object_magic = (m)
-/* Invalidate an object */
-#define OBJECT_INVALIDATE(o)   (o)->object_magic = 0
-/* Register an object which others could depend on */
-#define OBJECT_REGISTER(o)     (o)->object_id = unique_id()
-/* Register a dependancy for the object */
-#define OBJECT_SETDEP(o, r)    do { \
-    (o)->objdep_id = (r)->object_id; \
-    (o)->objdep_magic = (r)->object_magic; \
-} while (/* CONSTCOND */0)
-
-/* Returns TRUE if the object is valid and of expected type, FALSE if not */
-#define OBJECT_VALID(o, m)     ((o) != NULL && (o)->object_magic == (m))
-/* Returns TRUE if the object's dependancy matches with (d) */
-#define OBJECT_DEPENDS(o, d)   ((d) != NULL && \
-       (d)->object_magic == (o)->objdep_magic && \
-       (d)->object_id == (o)->objdep_id)
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/port.c b/Xisop/src/common/kernel/port.c
deleted file mode 100644 (file)
index 8e17e36..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-/* $Id: port.c,v 1.7 2004/10/14 15:05:23 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/task.h>
-#include <common/kernel/port.h>
-#include <common/kernel/main.h>
-#include <common/kernel/scheduler.h>
-#include <common/kernel/object.h>
-#include <common/kernel/statistic.h>
-#include <common/kernel/debug.h>
-#include <common/kernlib/hash.h>
-#include <common/kernlib/string.h>
-
-
-
-port_t *port_create(const char *name)
-{
-    bstr_t *bstr = NULL;
-    signum_t signum;
-
-    if (name != NULL) {
-       if ((bstr = bstr_new(name, 32, FALSE)) == NULL) {
-           STAT(STAT_PORTS_CREATED_NOMEM, 1);
-           DEBUG_PRINTF("* %T port_create(%p) - Out of memory\n", name);
-       } else {
-           SYSTABLE_RLOCK(SYSTABLE_PUBLICPORTS);
-           if ((hashtable_lookup(SYSTABLE(SYSTABLE_PUBLICPORTS), bstr->data,
-                           bstr->len)) != NULL) {
-               SYSTABLE_UNLOCK(SYSTABLE_PUBLICPORTS);
-               STAT(STAT_PORTS_CREATED_EXISTS, 1);
-               DEBUG_PRINTF("* %T port_create(%p) - Port exists (%s)\n",
-                       bstr->data);
-               bstr = bstr_free(bstr);
-           }
-       }
-    }
-    if (name == NULL || bstr != NULL) {
-       if ((signum = signal_alloc()) != -1) {
-           register task_t *task = CURTASK();
-           register port_t *port = NULL;
-
-           if ((port = (port_t *)spool_alloc(POOL_PORT)) != NULL) {
-               /* Validate object, and register it since message_t depends on
-                * us for reply-port validation
-                */
-               OBJECT_VALIDATE(port, OBJECT_PORT);
-               OBJECT_REGISTER(port);
-               /* Initialize other port_t fields */
-               port->sigtask = task;
-               port->signum = signum;
-               DLIST_INIT(&port->messages);
-               port->name = bstr;
-               if (bstr != NULL) {
-                   /* Public port, link via sysnode */
-                   SYSTABLE_UPGRADE(SYSTABLE_PUBLICPORTS);
-                   (void) hashtable_link(SYSTABLE(SYSTABLE_PUBLICPORTS),
-                                         (hashnode_t *)port, bstr->data,
-                                         bstr->len, FALSE);
-                   SYSTABLE_UNLOCK(SYSTABLE_PUBLICPORTS);
-               }
-               /* Register task resource */
-               SCHED_DISABLE();
-               DLIST_APPEND(&task->resources.ports, &port->tasknode);
-               SCHED_ENABLE();
-               STAT(STAT_PORTS_CREATED, 1);
-
-               return port;
-           } else {
-               if (bstr != NULL)
-                   SYSTABLE_UNLOCK(SYSTABLE_PUBLICPORTS);
-               STAT(STAT_PORTS_CREATED_NOMEM, 1);
-               DEBUG_PRINTF("* %T port_create(%p) - Out of memory\n", name);
-           }
-           signal_free(SIGMASK(signum));
-       } else {
-           if (bstr != NULL)
-               SYSTABLE_UNLOCK(SYSTABLE_PUBLICPORTS);
-           STAT(STAT_PORTS_CREATED_NOSIG, 1);
-           DEBUG_PRINTF("* %T port_create(%p) - Out of signals\n", name);
-       }
-    }
-
-    if (bstr != NULL)
-       bstr_free(bstr);
-
-    return NULL;
-}
-
-
-/* Can destroy a port of any task. */
-port_t *port_destroy(port_t *port)
-{
-    if (OBJECT_VALID(port, OBJECT_PORT)) {
-       register task_t *task = port->sigtask;
-
-       SCHED_DISABLE();
-       OBJECT_INVALIDATE(port);
-       _signal_free(task, PORT_SIGMASK(port));
-       /* Unlink task resource, linked via tasknode */
-       DLIST_UNLINK(&task->resources.ports, &port->tasknode);
-       SCHED_ENABLE();
-       if (port->name != NULL) {
-           bstr_free(port->name);
-           /* Unlink system resource, linked via sysnode */
-           SYSTABLE_WLOCK(SYSTABLE_PUBLICPORTS);
-           hashtable_unlink(SYSTABLE(SYSTABLE_PUBLICPORTS),
-                   (hashnode_t *)port);
-           SYSTABLE_UNLOCK(SYSTABLE_PUBLICPORTS);
-       }
-       spool_free(POOL_PORT, (pnode_t *)port);
-       STAT(STAT_PORTS_DESTROYED, 1);
-    } else {
-       STAT(STAT_PORTS_DESTROYED_FAILED, 1);
-       DEBUG_PRINTF("* %T port_destroy(%p)\n", port);
-    }
-
-    return NULL;
-}
-
-
-port_t *port_find(const char *name)
-{
-    register port_t *port = NULL;
-
-    if (name != NULL) {
-       SYSTABLE_RLOCK(SYSTABLE_PUBLICPORTS);
-       port = (port_t *)hashtable_lookup(SYSTABLE(SYSTABLE_PUBLICPORTS),
-               name, strnlen(name, 32));
-       SYSTABLE_UNLOCK(SYSTABLE_PUBLICPORTS);
-    }
-
-    if (port != NULL)
-       STAT(STAT_PORTS_FIND_FOUND, 1);
-    else
-       STAT(STAT_PORTS_FIND_NOTFOUND, 1);
-
-    return port;
-}
-
-
-bool port_send(port_t *port, port_t *replyport, message_t *msg)
-{
-    bool ok = FALSE;
-    message_t *tmsg;
-
-    if (OBJECT_VALID(port, OBJECT_PORT) && msg != NULL) {
-       ok = TRUE;
-       if (replyport != NULL) {
-           if (OBJECT_VALID(replyport, OBJECT_PORT)) {
-               msg->replyport = replyport;
-               OBJECT_SETDEP(msg, replyport);
-           } else
-               ok = FALSE;
-       } else
-           msg->replyport = NULL;
-       /* Queue message */
-       SCHED_DISABLE();
-       tmsg = DLIST_TOP(&port->messages);
-       DLIST_APPEND(&port->messages, (node_t *)msg);
-       SCHED_ENABLE();
-       /* Notify that a message arrived, but only if the port was previously
-        * empty.
-        */
-       if (tmsg == NULL)
-           signal_send(port->sigtask, PORT_SIGMASK(port));
-    }
-
-    if (ok)
-       STAT(STAT_PORTS_SEND, 1);
-    else {
-       STAT(STAT_PORTS_SEND_FAILED, 1);
-       DEBUG_PRINTF("* %T port_send(%p, %p, %p)\n", port, replyport, msg);
-    }
-
-    return ok;
-}
-
-
-message_t *port_get(port_t *port)
-{
-    register message_t *msg = NULL;
-
-    if (OBJECT_VALID(port, OBJECT_PORT)) {
-       SCHED_DISABLE();
-       if ((msg = DLIST_TOP(&port->messages)) != NULL)
-           DLIST_UNLINK(&port->messages, (node_t *)msg);
-       SCHED_ENABLE();
-    } else {
-       STAT(STAT_PORTS_GET_FAILED, 1);
-       DEBUG_PRINTF("* %T port_get(%p)\n", port);
-    }
-
-    if (msg != NULL)
-       STAT(STAT_PORTS_GET, 1);
-
-    return msg;
-}
-
-
-bool port_reply(message_t *msg)
-{
-    bool ok = FALSE;
-
-    if (msg != NULL && OBJECT_DEPENDS(msg, msg->replyport)) 
-       ok = port_send(msg->replyport, NULL, msg);
-
-    if (ok)
-       STAT(STAT_PORTS_REPLY, 1);
-    else {
-       STAT(STAT_PORTS_REPLY_FAILED, 1);
-       DEBUG_PRINTF("* %T port_reply(%p)\n", msg);
-    }
-
-    return ok;
-}
-
-
-/* Somewhat like poll(), but returns the port which caused the awakening.
- * The task argument is optional, and specifies a prefered task to run next,
- * or NULL. Note that a task can only wait for messages on it's own ports.
- */
-port_t *port_wait(port_t **ports, u_int32_t num, task_t *yield)
-{
-    register port_t *port = NULL;
-
-    if (ports != NULL && num > 0) {
-       register sigmask_t sigmask = 0;
-       register u_int32_t i;
-
-       SCHED_DISABLE();
-       /* By definition, a port has a tied signal. Form the sigmask. */
-       for (i = 0; i < num; i++) {
-           register port_t *p = ports[i];
-
-           if (OBJECT_VALID(p, OBJECT_PORT)) {
-               sigmask |= PORT_SIGMASK(p);
-               if (DLIST_TOP(&p->messages) != NULL) {
-                   port = p;
-                   break;
-               }
-           }
-       }
-       SCHED_ENABLE();
-       /* Only wait if all ports were empty */
-       if (port == NULL) {
-           STAT(STAT_PORTS_WAIT, 1);
-           sigmask = signal_wait(sigmask, yield);
-           STAT(STAT_PORTS_WAIT_RETURNED_SLEEP, 1);
-           SCHED_DISABLE();
-           for (i = 0; i < num; i++) {
-               register port_t *p = ports[i];
-
-               if (OBJECT_VALID(p, OBJECT_PORT) &&
-                       (sigmask & PORT_SIGMASK(p))) {
-                   port = p;
-                   break;
-               }
-           }
-           /* A big problem! We awaken, but not as the result of one of the
-            * port signals. When such a thing can occur, the task should
-            * use signal_wait() and manually include in the mask the wanted
-            * port signals, not port_wait(). We'll return NULL of course.
-            */
-           if (i == num) {
-               STAT(STAT_PORTS_WAIT_RETURNED_NOSIG, 1);
-               DEBUG_PRINTF(
-                       "- %T port_wait(%p, %u, %p) - Unexpected signal\n",
-                       ports, num, yield);
-           }
-           SCHED_ENABLE();
-       } else
-           STAT(STAT_PORTS_WAIT_RETURNED_IMMEDIATE, 1);
-    } else {
-       STAT(STAT_PORTS_WAIT_FAILED, 1);
-       DEBUG_PRINTF("* %T port_wait(%p, %u, %p)\n", ports, num, yield);
-    }
-
-    return port;
-}
-
-
-/* Unlinks all currently queued messages (if any) from the supplied port_t.
- * Should normally be performed on the tasks of the caller process only.
- */
-bool port_flush(port_t *port)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(port, OBJECT_PORT)) {
-       ok = TRUE;
-       SCHED_DISABLE();
-       if (DLIST_TOP(&port->messages) != NULL)
-           DLIST_INIT(&port->messages);
-       SCHED_ENABLE();
-       STAT(STAT_PORTS_FLUSHED, 1);
-    } else {
-       STAT(STAT_PORTS_FLUSHED_FAILED, 1);
-       DEBUG_PRINTF("* %T port_flush(%p)\n", port);
-    }
-
-    return ok;
-}
diff --git a/Xisop/src/common/kernel/port.h b/Xisop/src/common/kernel/port.h
deleted file mode 100644 (file)
index 0a2ee44..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/* $Id: port.h,v 1.2 2004/01/18 17:43:00 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNEL_PORT_H
-#define KERNEL_PORT_H
-
-
-
-#include <common/types.h>
-#include <common/kernel/task.h>
-#include <common/kernel/signal.h>
-#include <common/kernel/scheduler.h>
-#include <common/kernel/main.h>
-#include <common/kernel/memory.h>
-#include <common/kernlib/hash.h>
-#include <common/kernlib/string.h>
-
-
-
-struct port {
-    hashnode_t sysnode;
-    node_t tasknode;           /* Link to task_t ressources list_t */
-    /* Validity sceal, message_t can depend on us */
-    u_int32_t object_magic, object_id;
-    /* Other */
-    task_t *sigtask;
-    signum_t signum;
-    list_t messages;
-    /* The following are used for public ports */
-    bstr_t *name;
-};
-
-struct message {
-    pnode_t node;      /* Allows for linking and using pool_t */
-    /* The following two are used to allow replying back, but only to the
-     * actually expected reply port.
-     */
-    port_t *replyport;
-    /* Object dependancy */
-    u_int32_t objdep_magic, objdep_id;
-};
-
-/* This message type is made to pass through the special multiplexed port */
-/* XXX */
-struct mmessage {
-    message_t node;
-    int type;
-    union {
-    } u;
-};
-
-
-
-#define PORT_SIGMASK(p)                SIGMASK((p)->signum)
-
-
-
-port_t *port_create(const char *);
-port_t *port_destroy(port_t *);
-port_t *port_find(const char *);
-bool port_send(port_t *, port_t *, message_t *);
-message_t *port_get(port_t *);
-bool port_reply(message_t *);
-port_t *port_wait(port_t **, u_int32_t, task_t *);
-bool port_flush(port_t *);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/scheduler.c b/Xisop/src/common/kernel/scheduler.c
deleted file mode 100644 (file)
index f9329a4..0000000
+++ /dev/null
@@ -1,382 +0,0 @@
-/* $Id: scheduler.c,v 1.5 2004/01/29 21:52:12 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/main.h>
-#include <common/kernel/scheduler.h>
-#include <common/kernel/task.h>
-#include <common/kernel/statistic.h>
-#include <common/kernel/object.h>
-#include <processor/support.h>
-
-
-
-/* The famous initial context (the first scheduler interrupt context save
- * operation saves main()'s context there. This context is resumed when there
- * are no more tasks in the ready queue to run, in which case main()'s CPU
- * ideling loop resumes.
- */
-static _ctx_t _scontext;
-
-
-
-/* Used to initialize the xisop_root necessary fields */
-void scheduler_init(void)
-{
-    /* Initialize scheduler recursive lock, and obtain it. The system will
-     * need to SCHED_ENABLE() to start the scheduler.
-     */
-    _rlock_init(&root->sched_lock);
-    _rlock_acquire(&root->sched_lock);
-    DLIST_INIT(&root->tasks_ready);
-    DLIST_INIT(&root->tasks_wait);
-    DLIST_INIT(&root->tasks_dead);
-    root->curtask = NULL;
-    root->curctx = &_scontext;
-}
-
-
-/* This function only has effect if the scheduler recursive lock is free,
- * in which case scheduling is enabled. When so, it evaluates which task
- * should run next and internally performs task and context switching if
- * needed, via root->curtask and _scontext, the static context buffer used
- * by the scheduler interrupt handler to store and load CPU context. We are
- * only dealing with the tasks which are currently on the root->tasks_ready
- * queue, and are working appropriately around the events of no tasks in the
- * queue and the first context switch, and against recursion.
- *
- * What the scheduler timer interrupt does is disable the interrupt source,
- * save the current user CPU context in root->curctx, which may be _scontext
- * or old task context, execute the _FACILITY_SCHEDTIMER hooks calling
- * facility_exechooks(), call us, load back the saved user CPU context
- * from root->curctx, re-enable the interrupt source and return from exception
- * to the new context's PC address. So basically we are between the context
- * save and load operations, and can access and alter root->curtask and
- * root->curctx, thus the buffer it uses to load the context back.
- *
- * Our task priority scheduling algorithm uses a credits attribution method
- * where when starting a round, each task in the queue receives credits
- * according to it's specific priority. The round expires when none of the
- * tasks have any credits left, in which case a new round restarts over.
- * During a round, an effort is made to both allow tasks with the most credits
- * to run more often and faster than others, while still distributing as much
- * as possible their turns evenly to make the signal and message port systems
- * work as efficiently as possible in all cases.
- *
- * This does not account for how long each task has run, a task may
- * take any time from 0 to the scheduler rate before it is interrupted and
- * a credit is substracted from it. Another type of scheduler could be
- * more suitable for a realtime system.
- */
-void old_schedule(void)
-{
-    /* Do nothing unless the scheduler is enabled */
-    if (_rlock_try(&root->sched_lock)) {
-       register task_t *ntsk, *old;
-
-       if ((old = root->curtask) == NULL)
-           ntsk = DLIST_TOP(&root->tasks_ready);
-       else {
-           if (old->state == STATE_RUN)
-               old->state = STATE_READY;
-           for (;;) {
-               register task_t *tsk;
-               register priority_t credit;
-
-               /* Find which task has the most credits and deserves next run,
-                * but continue the loop at previous task, otherwise the
-                * highest priority task will get all turns at once until it
-                * reaches equality with other tasks.
-                */
-               credit = -128;
-               tsk = old;
-               ntsk = NULL;
-               for (;;) {
-                   if ((tsk = (task_t *)tsk->node.node.next) == NULL)
-                       tsk = DLIST_TOP(&root->tasks_ready);
-                   if (tsk != old) {
-                       if (credit < tsk->credits) {
-                           credit = tsk->credits;
-                           ntsk = tsk;
-                       }
-                   } else
-                       break;
-               }
-               if (ntsk == NULL) {
-                   /* If this happens there is only one task in the queue,
-                    * or none. Revert back to previous task, if any.
-                    */
-                   if (DLIST_NODES(&root->tasks_ready) > 0)
-                       ntsk = old;
-                   else break;
-               }
-
-               if (credit == -128 /* XXX && ntsk != old */) {
-                   /* All out of credits, redistribute them. This is the
-                    * end and beginning of a new round.
-                    */
-                   DLIST_FOREACH(&root->tasks_ready, tsk) {
-                       if ((tsk->credits = tsk->priority) == -128)
-                           tsk->credits++;
-                   }
-                   continue;
-               }
-
-               break;
-           }
-       }
-
-       if (ntsk != NULL) {
-           /* This is the next task to run */
-           ntsk->credits--;
-           if (ntsk != old) {
-               /* Perform actual context switch */
-               STAT(STAT_SCHED_PREEMPTED, 1);
-               ntsk->state = STATE_RUN;
-               root->curtask = ntsk;
-               root->curctx = &ntsk->ctx;
-           }
-       } else {
-           root->curtask = NULL;
-           root->curctx = &_scontext;
-       }
-
-       _rlock_release(&root->sched_lock);
-    }
-}
-
-/* Because there seems to be a bug with the previous function and that
- * all we need for testing and building the rest of Xisop is at least
- * round robin, here is a function which at least works for now.
- */
-void schedule(task_t *pref)
-{
-    if (_rlock_try(&root->sched_lock)) {
-       register task_t *tsk;
-
-       /* First evaluate if requested task is ok to switch to */
-       if (OBJECT_VALID(pref, OBJECT_TASK) && pref != root->curtask &&
-               pref->state == STATE_READY)
-           tsk = pref;
-       else {
-           if ((tsk = root->curtask) == NULL)
-               tsk = DLIST_TOP(&root->tasks_ready);
-           else {
-               /* The current task may not be in the ready list anymore */
-               if (tsk->state == STATE_READY || tsk->state == STATE_RUN) {
-                   tsk->state = STATE_READY;
-                   if ((tsk = DLIST_NEXT(tsk)) == NULL)
-                       tsk = DLIST_TOP(&root->tasks_ready);
-               } else
-                   tsk = DLIST_TOP(&root->tasks_ready);
-           }
-       }
-       if (tsk != NULL) {
-           tsk->state = STATE_RUN;
-           root->curtask = tsk;
-           root->curctx = &tsk->ctx;
-       } else {
-           /* No tasks in the ready queue to run, return to the original
-            * main() context, which idles the CPU as much as possible
-            * using sys_idle().
-            */
-           root->curtask = NULL;
-           root->curctx = &_scontext;
-       }
-       _rlock_release(&root->sched_lock);
-    }
-}
-
-
-/* Allows to make a task sleep forcibly. The only way it can then wake up
- * is by task_wakeup() using at least one of the bits in the flags.
- */
-void task_sleep(task_t *task, u_int32_t flags, task_t *yield)
-{
-    bool current = FALSE;
-
-    SCHED_DISABLE();
-    if (OBJECT_VALID(task, OBJECT_TASK) &&
-           (task->state == STATE_READY || task->state == STATE_RUN)) {
-       task->sleepflags = flags;
-       task->state = STATE_WAIT;
-       DLIST_SWAP(&root->tasks_wait, &root->tasks_ready, (node_t *)task,
-               FALSE);
-       if (task == root->curtask)
-           current = TRUE;
-    }
-    SCHED_ENABLE();
-    if (current)
-       _yield(yield);
-}
-
-/* Awakes a task which should have been put asleep using task_sleep().
- * The task is only awaken if at least one of the reasons in flags matches.
- */
-bool task_wakeup(task_t *task, u_int32_t flags)
-{
-    bool ok = FALSE;
-
-    SCHED_DISABLE();
-    if (OBJECT_VALID(task, OBJECT_TASK) &&
-           task->state == STATE_WAIT && (task->sleepflags & flags)) {
-       task->state = STATE_READY;
-       task->sleepflags = 0;
-       task->credits = task->priority;
-       if (task->credits == -128)
-           task->credits++;
-       DLIST_SWAP(&root->tasks_ready, &root->tasks_wait, (node_t *)task,
-               FALSE);
-       ok = TRUE;
-    }
-    SCHED_ENABLE();
-
-    return ok;
-}
-
-
-void sched_disable(void)
-{
-    SCHED_DISABLE();
-}
-
-void sched_enable(void)
-{
-    SCHED_ENABLE();
-}
-
-
-/* Nestled locking is not permitted with these locks */
-void lock_acquire(_lock_t *lock)
-{
-    /* Always immediately _yield() unless we can obtain the lock.
-     * This way we use the less CPU time possible while at the same time
-     * allowing the locker to eventually release the lock.
-     */
-    for (;;) {
-       if (_lock_try(lock))
-           break;
-       _yield(NULL);
-    }
-}
-
-void lock_release(_lock_t *lock)
-{
-    _lock_release(lock);
-}
-
-
-/* A lock type permitting multiple readers but exclusive access for write */
-void rwlock_init(rwlock_t *lock)
-{
-    _lock_init(&lock->exclusive_lock);
-    _rlock_init(&lock->recursive_lock);
-    lock->state = RWLOCK_SLOCKED;
-}
-
-void rwlock_acquire(rwlock_t *lock, bool exclusive)
-{
-    lock_acquire(&lock->exclusive_lock);
-    if (exclusive) {
-       while (!_rlock_try(&lock->recursive_lock))
-           _yield(NULL);
-       lock->state = RWLOCK_XLOCKED;
-       _rlock_release(&lock->recursive_lock);
-    } else {
-       _rlock_acquire(&lock->recursive_lock);
-       lock->state = RWLOCK_SLOCKED;
-       _lock_release(&lock->exclusive_lock);
-    }
-}
-
-void rwlock_release(rwlock_t *lock)
-{
-    switch (lock->state) {
-    case RWLOCK_SLOCKED:
-       _rlock_release(&lock->recursive_lock);
-       break;
-    case RWLOCK_XLOCKED:
-       lock->state = RWLOCK_SLOCKED;
-       _lock_release(&lock->exclusive_lock);
-       break;
-    }
-}
-
-bool rwlock_try(rwlock_t *lock, bool exclusive)
-{
-    bool ok = FALSE;
-
-    if (_lock_try(&lock->exclusive_lock)) {
-       if (exclusive) {
-           if (_rlock_try(&lock->recursive_lock)) {
-               _rlock_release(&lock->recursive_lock);
-               _lock_release(&lock->exclusive_lock);
-           } else {
-               lock->state = RWLOCK_XLOCKED;
-               ok = TRUE;
-           }
-       } else {
-           _rlock_acquire(&lock->recursive_lock);
-           lock->state = RWLOCK_SLOCKED;
-           _lock_release(&lock->exclusive_lock);
-           ok = TRUE;
-       }
-    }
-
-    return ok;
-}
-
-void rwlock_upgrade(rwlock_t *lock)
-{
-    if (lock->state == RWLOCK_SLOCKED) {
-       lock_acquire(&lock->exclusive_lock);
-       _rlock_release(&lock->recursive_lock);
-       while (!_rlock_try(&lock->recursive_lock))
-           _yield(NULL);
-       lock->state = RWLOCK_XLOCKED;
-       _rlock_release(&lock->recursive_lock);
-    }
-}
-
-void rwlock_downgrade(rwlock_t *lock)
-{
-    if (lock->state == RWLOCK_XLOCKED) {
-       _rlock_acquire(&lock->recursive_lock);
-       lock->state = RWLOCK_SLOCKED;
-       _lock_release(&lock->exclusive_lock);
-    }
-}
diff --git a/Xisop/src/common/kernel/scheduler.h b/Xisop/src/common/kernel/scheduler.h
deleted file mode 100644 (file)
index 02b95ce..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/* $Id: scheduler.h,v 1.2 2004/01/19 00:03:23 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNEL_SCHEDULER_H
-#define KERNEL_SCHEDULER_H
-
-
-
-#include <common/types.h>
-#include <common/kernel/task.h>
-#include <processor/support.h>
-
-
-
-/* Scheduler control without affecting the scheduler interrupt */
-#define SCHED_DISABLE()                _rlock_acquire(&root->sched_lock)
-#define SCHED_ENABLE()         _rlock_release(&root->sched_lock)
-
-/* Sleep reason flags for task_sleep() and task_wakeup() */
-#define TSF_SIGNAL             (1L << 0)
-#define TSF_KERNEL             (1L << 1)
-#define TSF_CUSTOM             (1L << 2)
-
-/* State of an rwlock_t */
-enum _rwlock_states {
-    RWLOCK_SLOCKED,
-    RWLOCK_XLOCKED
-};
-
-struct rwlock {
-    _lock_t exclusive_lock;
-    _rlock_t recursive_lock;
-    enum _rwlock_states state;
-};
-
-
-
-void scheduler_init(void);
-void schedule(task_t *);
-void task_sleep(task_t *, u_int32_t, task_t *);
-bool task_wakeup(task_t *, u_int32_t);
-void sched_disable(void);
-void sched_enable(void);
-
-void lock_acquire(_lock_t *);
-void lock_release(_lock_t *);
-void rwlock_init(rwlock_t *);
-void rwlock_acquire(rwlock_t *, bool);
-void rwlock_release(rwlock_t *);
-bool rwlock_try(rwlock_t *, bool);
-void rwlock_upgrade(rwlock_t *);
-void rwlock_downgrade(rwlock_t *);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/signal.c b/Xisop/src/common/kernel/signal.c
deleted file mode 100644 (file)
index a882416..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/* $Id: signal.c,v 1.3 2004/06/04 02:15:47 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/signal.h>
-#include <common/kernel/task.h>
-#include <common/kernel/scheduler.h>
-#include <common/kernel/main.h>
-#include <common/kernel/syscall.h>
-#include <common/kernel/object.h>
-#include <common/kernel/statistic.h>
-#include <common/kernel/debug.h>
-
-
-
-/* Attempts to allocate a general purpose user signal from the current task */
-signum_t signal_alloc(void)
-{
-    register signum_t signum = -1;
-    register task_t *task = CURTASK();
-
-    if (task->sigalloc != 0xFFFFFFFF) {
-       register sigmask_t sigmask = task->sigalloc;
-
-       for (signum = 0; signum < 32; signum++) {
-           if ((sigmask & SIGMASK(signum)) == 0) {
-               sigmask |= SIGMASK(signum);
-               task->sigalloc = sigmask;
-               STAT(STAT_SIGNALS_ALLOC, 1);
-               break;
-           }
-       }
-       if (signum == 32)
-           signum = -1;
-    } else {
-       STAT(STAT_SIGNALS_ALLOC_NOSIG, 1);
-       DEBUG_PRINTF("- %T signal_alloc() - Out of signals\n");
-    }
-
-    return signum;
-}
-
-
-void _signal_free(task_t *task, sigmask_t sigmask)
-{
-    if (OBJECT_VALID(task, OBJECT_TASK)) {
-       /* Refuse to free reserved signals */
-       sigmask &= ~SIGRESMASK;
-       /* But free all other requested ones */
-       task->sigalloc &= ~sigmask;
-       STAT(STAT_SIGNALS_FREE, 1);
-    }
-}
-
-
-/* Frees back specified allocated signals of the current process, for future
- * obtention with signal_alloc() again.
- */
-void signal_free(sigmask_t sigmask)
-{
-    _signal_free(CURTASK(), sigmask);
-}
-
-
-/* Suspends the current task until at least one signal in sigmask is received
- * by it. The task is moved to the wait queue and sigwait is set, as
- * opposition to yield() which does not change the task state and just causes
- * a reschedule.
- * Obviously, using a sigmask of 0 here woild suspend the task indefinitely,
- * and is invalid. If the task needs to be awakened on a timeout event, it
- * should allocate a signal for that event and ensure to receive that signal
- * when the delay expires. This can be done using a timer.device or another
- * task.
- * The optional task argument, which may be NULL, specifies a preference to
- * which task to run next (as we yield()).
- */
-sigmask_t signal_wait(sigmask_t sigmask, task_t *yield)
-{
-    register sigmask_t recvmask = 0;
-
-    if (sigmask != 0) {
-       register task_t *t = CURTASK();
-
-       sigmask |= SIGRESMASK;          /* Always awake on those */
-
-       SCHED_DISABLE();
-       /* Set new sigwait mask */
-       t->sigwait = sigmask;
-       SCHED_ENABLE();
-
-       /* Swap task to waiting queue (we know that we are currently in the
-        * ready one, in STATE_RUN, otherwise we would not be running), and
-        * relay control back to scheduler immediately.
-        */
-       task_sleep(t, TSF_SIGNAL, yield);
-
-       /* If we get here, it's because we were swapped back to the ready queue
-        * as the result of receiving a signal we were waiting for, and
-        * were awaken by the scheduler, and we are back in STATE_RUN. Clear
-        * the sigwait mask, but also return it so that the caller knows which
-        * signal(s) caused our task to wake up again.
-        */
-       SCHED_DISABLE();
-       recvmask = t->sigrecv;
-       t->sigrecv = 0;
-       SCHED_ENABLE();
-
-       STAT(STAT_SIGNALS_WAIT_RETURNED_SLEEP, 1);
-    } else {
-       STAT(STAT_SIGNALS_WAIT_FAILED, 1);
-       DEBUG_PRINTF("* %T signal_wait(%b, %p)\n", sigmask, yield);
-    }
-
-    return recvmask;
-}
-
-
-/* Sends a signal to a task. The task is immediately moved to the ready
- * queue if it currently was waiting for it. The current task is however
- * left executing, but may _yield() if it wants the other end to be able to
- * react to the signal as soon as possible. Otherwise the scheduler frequency
- * and tasks priorities will decide when the other end can run.
- */
-void signal_send(task_t *task, sigmask_t sigmask)
-{
-    if (OBJECT_VALID(task, OBJECT_TASK) && sigmask != 0) {
-       bool awake = FALSE;
-
-       SCHED_DISABLE();
-       /* Apply signals */
-       task->sigrecv |= sigmask;
-       SCHED_ENABLE();
-
-       STAT(STAT_SIGNALS_SEND, 1);
-
-       /* If needed, swap task to ready queue */
-       if ((task->sigwait & task->sigrecv) != 0)
-           awake = task_wakeup(task, TSF_SIGNAL);
-
-       /* XXX UGH! Unless we _yield(), synchronization problems quickly occur
-        * among communicating tasks, they eventually all reside in the wait
-        * queue, in which case they obviously deadlock. And strangely enough,
-        * we have to _yield() twice to solve this issue! Why is currently
-        * still a mystery, but possibly that it has to do with the fact that
-        * when communicating through message ports, we expect a reply?
-        * Maybe that the scheduler should be left to evaluate when a task
-        * should be moved to the waiting queue, and when it needs to be
-        * brought back on the ready queue because it received an expected
-        * signal... rather than having tasks do so themselves, which is what
-        * we currently are doing.
-        */
-       if (awake) {
-           STAT(STAT_SIGNALS_SEND_WOKE, 1);
-           _yield(task);
-           _yield(NULL);
-       }
-    } else {
-       STAT(STAT_SIGNALS_SEND_FAILED, 1);
-       DEBUG_PRINTF("* %T signal_send(%p, %b)\n", task, sigmask);
-    }
-}
diff --git a/Xisop/src/common/kernel/signal.h b/Xisop/src/common/kernel/signal.h
deleted file mode 100644 (file)
index 50eca01..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/* $Id: signal.h,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNEL_SIGNAL_H
-#define KERNEL_SIGNAL_H
-
-
-
-#include <common/types.h>
-#include <common/kernel/task.h>
-
-
-
-/* Reserved signals */
-#define SIGRESERVED    2
-#define SIGRESMASK     0x00000003L
-#define SIGTERM                0
-#define SIGPOLL                1
-
-
-/* Useful to form a sigmask_t from signum_t */
-#define SIGMASK(n)     (sigmask_t )(1L << (n))
-
-
-signum_t signal_alloc(void);
-void signal_free(sigmask_t);
-void _signal_free(task_t *, sigmask_t);
-sigmask_t signal_wait(sigmask_t, task_t *);
-void signal_send(task_t *, sigmask_t);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/statistic.c b/Xisop/src/common/kernel/statistic.c
deleted file mode 100644 (file)
index 154823b..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/* $Id: statistic.c,v 1.3 2004/06/04 02:15:47 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/statistic.h>
-#include <common/kernel/debug.h>
-#include <common/kernel/main.h>
-#include <common/kernlib/string.h>
-#include <config.h>
-
-
-
-#ifdef STATISTICS
-
-
-
-/* Should match with stat_keys enum of statistic.h */
-const static char *stat_strings[] = {
-    "mem.mchunks.attach",
-    "mem.mchunks.attach.failed",
-    "mem.mchunks.detach",
-    "mem.mchunks.detach.failed",
-    "mem.pages.alloc",
-    "mem.pages.alloc.nomem",
-    "mem.pages.free",
-    "mem.pages.free.failed",
-    "mem.pages.buffered",
-    "mem.pages.unbuffered",
-    "mem.pages.reused",
-    "mem.pools.created",
-    "mem.pools.created.failed",
-    "mem.pools.enlarged",
-    "mem.pools.destroyed",
-    "mem.pools.destroyed.failed",
-    "mem.pools.alloc",
-    "mem.pools,alloc.failed",
-    "mem.pools.alloc.nomem",
-    "mem.pools.free",
-    "mem.pools.free.failed",
-    "mem.mpools.created",
-    "mem.mpools.created.failed",
-    "mem.mpools.destroyed",
-    "mem.mpools.destroyed.failed",
-    "mem.mpools.alloc",
-    "mem.mpools.alloc.failed",
-    "mem.mpools.alloc.nomem",
-    "mem.mpools.free",
-    "mem.mpools.free.failed",
-    "syscalls.invalid",
-    "syscalls.invoked",
-    "hooks.attached",
-    "hooks.attached.failed",
-    "hooks.attached.nomem",
-    "hooks.detached",
-    "hooks.detached,failed",
-    "hooks.detached.noexist",
-    "hooks.expired",
-    "hooks.executed",
-    "hooks.skipped",
-    "facility.disabled",
-    "facility.disabled.failed",
-    "facility.enabled",
-    "facility.enabled.failed",
-    "facility.executed",
-    "facility.executed.failed",
-    "facility.executed.locked",
-    "sched.preempted",
-    "tasks.alloc",
-    "tasks.alloc.failed",
-    "tasks.alloc.nomem",
-    "tasks.free",
-    "tasks.free.failed",
-    "tasks.started",
-    "tasks.started.failed",
-    "tasks.ended",
-    "tasks.ended.failed",
-    "ports.created",
-    "ports.created.exists",
-    "ports.created.nomem",
-    "ports.created.nosig",
-    "ports.destroyed",
-    "ports.destroyed.failed",
-    "ports.find.found",
-    "ports.find.notfound",
-    "ports.send",
-    "ports.send.failed",
-    "ports.send",
-    "ports.send.failed",
-    "ports.get",
-    "ports.get.failed",
-    "ports.reply",
-    "ports.reply.failed",
-    "ports.wait",
-    "ports.wait.failed",
-    "ports.wait.sleep",
-    "ports.wait.returned.immediate",
-    "ports.wait.returned.sleep",
-    "ports.wait.returned.nosig",
-    "ports.flushed",
-    "ports.flushed.failed",
-    "signals.alloc",
-    "signals.alloc.nosig",
-    "signals.free",
-    "signals.wait",
-    "signals.wait.failed",
-    "signals.wait.returned.sleep",
-    "signals.send",
-    "signals.send.failed",
-    "signals.send.woke",
-    NULL
-};
-
-
-
-void statistic_init(void)
-{
-    register u_int32_t i;
-
-    for (i = 0; i < (enum stat_keys)STAT_MAX; i++)
-       root->stats[i] = 0;
-}
-
-
-void stat_dump(void)
-{
-    register u_int32_t i;
-
-    for (i = 0; i < (enum stat_keys)STAT_MAX; i++)
-       DEBUG_PRINTF("%u\t%s\n", root->stats[i], stat_strings[i]);
-}
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/statistic.h b/Xisop/src/common/kernel/statistic.h
deleted file mode 100644 (file)
index 8024431..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/* $Id: statistic.h,v 1.2 2004/01/18 17:43:00 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNEL_STATISTIC_H
-#define KERNEL_STATISTIC_H
-
-
-
-#include <config.h>
-
-
-
-#ifndef STATISTICS
-
-#define STAT(k, m)
-
-#else
-
-
-
-enum stat_keys {
-    STAT_MCHUNKS_ATTACH = 0,
-    STAT_MCHUNKS_ATTACH_FAILED,
-    STAT_MCHUNKS_DETACH,
-    STAT_MCHUNKS_DETACH_FAILED,
-    STAT_PAGES_ALLOC,
-    STAT_PAGES_ALLOC_NOMEM,
-    STAT_PAGES_FREE,
-    STAT_PAGES_FREE_FAILED,
-    STAT_PAGES_BUFFERED,
-    STAT_PAGES_UNBUFFERED,
-    STAT_PAGES_REUSED,
-    STAT_POOLS_CREATED,
-    STAT_POOLS_CREATED_FAILED,
-    STAT_POOLS_ENLARGED,
-    STAT_POOLS_DESTROYED,
-    STAT_POOLS_DESTROYED_FAILED,
-    STAT_POOLS_ALLOC,
-    STAT_POOLS_ALLOC_FAILED,
-    STAT_POOLS_ALLOC_NOMEM,
-    STAT_POOLS_FREE,
-    STAT_POOLS_FREE_FAILED,
-    STAT_MPOOLS_CREATED,
-    STAT_MPOOLS_CREATED_FAILED,
-    STAT_MPOOLS_DESTROYED,
-    STAT_MPOOLS_DESTROYED_FAILED,
-    STAT_MPOOLS_ALLOC,
-    STAT_MPOOLS_ALLOC_FAILED,
-    STAT_MPOOLS_ALLOC_NOMEM,
-    STAT_MPOOLS_FREE,
-    STAT_MPOOLS_FREE_FAILED,
-    STAT_SYSCALLS_INVALID,
-    STAT_SYSCALLS_INVOKED,
-    STAT_HOOKS_ATTACHED,
-    STAT_HOOKS_ATTACHED_FAILED,
-    STAT_HOOKS_ATTACHED_NOMEM,
-    STAT_HOOKS_DETACHED,
-    STAT_HOOKS_DETACHED_FAILED,
-    STAT_HOOKS_DETACHED_NOEXIST,
-    STAT_HOOKS_EXPIRED,
-    STAT_HOOKS_EXECUTED,
-    STAT_HOOKS_SKIPPED,
-    STAT_FACILITY_DISABLED,
-    STAT_FACILITY_DISABLED_FAILED,
-    STAT_FACILITY_ENABLED,
-    STAT_FACILITY_ENABLED_FAILED,
-    STAT_FACILITY_EXECUTED,
-    STAT_FACILITY_EXECUTED_FAILED,
-    STAT_FACILITY_EXECUTED_LOCKED,
-    STAT_SCHED_PREEMPTED,
-    STAT_TASKS_ALLOC,
-    STAT_TASKS_ALLOC_FAILED,
-    STAT_TASKS_ALLOC_NOMEM,
-    STAT_TASKS_FREE,
-    STAT_TASKS_FREE_FAILED,
-    STAT_TASKS_STARTED,
-    STAT_TASKS_STARTED_FAILED,
-    STAT_TASKS_ENDED,
-    STAT_TASKS_ENDED_FAILED,
-    STAT_PORTS_CREATED,
-    STAT_PORTS_CREATED_EXISTS,
-    STAT_PORTS_CREATED_NOMEM,
-    STAT_PORTS_CREATED_NOSIG,
-    STAT_PORTS_DESTROYED,
-    STAT_PORTS_DESTROYED_FAILED,
-    STAT_PORTS_FIND_FOUND,
-    STAT_PORTS_FIND_NOTFOUND,
-    STAT_PORTS_SEND,
-    STAT_PORTS_SEND_FAILED,
-    STAT_PORTS_GET,
-    STAT_PORTS_GET_FAILED,
-    STAT_PORTS_REPLY,
-    STAT_PORTS_REPLY_FAILED,
-    STAT_PORTS_WAIT,
-    STAT_PORTS_WAIT_FAILED,
-    STAT_PORTS_WAIT_SLEEP,
-    STAT_PORTS_WAIT_RETURNED_IMMEDIATE,
-    STAT_PORTS_WAIT_RETURNED_SLEEP,
-    STAT_PORTS_WAIT_RETURNED_NOSIG,
-    STAT_PORTS_FLUSHED,
-    STAT_PORTS_FLUSHED_FAILED,
-    STAT_SIGNALS_ALLOC,
-    STAT_SIGNALS_ALLOC_NOSIG,
-    STAT_SIGNALS_FREE,
-    STAT_SIGNALS_WAIT,
-    STAT_SIGNALS_WAIT_FAILED,
-    STAT_SIGNALS_WAIT_RETURNED_SLEEP,
-    STAT_SIGNALS_SEND,
-    STAT_SIGNALS_SEND_FAILED,
-    STAT_SIGNALS_SEND_WOKE,
-    STAT_MAX
-};
-
-
-
-#define STAT(k, n)     root->stats[(enum stat_keys)(k)] += (n)
-
-
-
-void statistic_init(void);
-void statistic_dump(void);
-
-
-
-#endif
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/syscall.c b/Xisop/src/common/kernel/syscall.c
deleted file mode 100644 (file)
index 9df06e8..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/* $Id: syscall.c,v 1.2 2004/06/04 02:15:47 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* It also would be possible to simply use a structure with all the
- * function pointers of the various types... And have the user functions
- * refer those with the structure as well, just like for Xisop libraries...
- * However, this system is a little more secure for the kernel stack,
- * which state is always controled. It also allows to export an ID which
- * we can validate.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/main.h>
-#include <common/kernel/syscall.h>
-#include <common/kernel/statistic.h>
-#include <common/kernel/debug.h>
-#include <common/kernel/scheduler.h>
-#include <common/kernel/exception.h>
-#include <common/kernel/memory.h>
-#include <port/support.h> /* XXX */
-
-
-
-static void _sys_getroot(void *, void *);
-static void _sys_int_disable(void *, void *);
-static void _sys_int_enable(void *, void *);
-static void _sys_idle(void *, void *);
-static void _sys_custom(void *, void *);
-
-
-
-/* Should match with enum in syscall.h */
-static void (*_syscalls[])(void *, void *) = {
-    _sys_getroot,
-    _sys_int_disable,
-    _sys_int_enable,
-    _sys_idle,
-    _sys_custom
-};
-
-
-
-/* Called by port-specific code before initializing interrupt facilities */
-void syscall_init(void)
-{
-    root->syscalls = _syscalls;
-}
-
-
-/* The following consist of the kernel-side functions which execute in
- * supervisor mode.
- */
-
-/* Syscall trap handler */
-void _scatch(u_int32_t func, void *res, void *args)
-{
-    if (func < (enum syscalls)SYS_MAX && root->syscalls[func])
-       root->syscalls[func](res, args);
-    else {
-       STAT(STAT_SYSCALLS_INVALID, 1);
-       DEBUG_PRINTF("* %T _scatch(%u, %p, %p) - Invalid syscall number\n",
-               func, res, args);
-    }
-    STAT(STAT_SYSCALLS_INVOKED, 1);
-}
-
-
-static void _sys_getroot(void *res, void *args)
-{
-    struct _sres {
-       struct xisop_root *root;
-    } *sres = res;
-
-    sres->root = root;
-}
-
-
-/* ARGSUSED */
-static void _sys_int_disable(void *res, void *args)
-{
-    _splhigh();
-}
-
-/* ARGSUSED */
-static void _sys_int_enable(void *res, void *args)
-{
-    _spl0();
-}
-
-/* ARGSUSED */
-static void _sys_idle(void *res, void *args)
-{
-    _idle();
-}
-
-
-static void _sys_custom(void *res, void *args)
-{
-    struct _sargs {
-       void (*func)(void *, void *);
-       void *args;
-    } *sargs = args;
-
-    sargs->func(res, sargs->args);
-}
-
-
-
-/* And here are the functions which are called from userspace to trigger
- * system calls.
- */
-
-/* Returns the Xisop system pointer. This obviously should be used with care */
-struct xisop_root *sys_getroot(void)
-{
-    struct _sres {
-       struct xisop_root *root;
-    } sres;
-
-    _syscall(SYS_GETROOT, &sres, NULL);
-
-    return sres.root;
-}
-
-
-/* And these allow to disable all interrupts, which of course also causes
- * the scheduler to be disabled. Should however not generally be used as a
- * substitute to sched_disable().
- */
-void sys_int_disable(void)
-{
-    _syscall(SYS_INT_DISABLE, NULL, NULL);
-}
-
-void sys_int_enable(void)
-{
-    _syscall(SYS_INT_ENABLE, NULL, NULL);
-}
-
-/* Causes the CPU to sleep until the next interrupt occurs */
-void sys_idle(void)
-{
-    _syscall(SYS_IDLE, NULL, NULL);
-}
-
-
-/* Since Xisop does not use MMU, and in now way claims to be secure against
- * it's own tasks, other than providing clean facilities, a very useful
- * syscall to execute arbitrary code in supervisor mode. If one needs
- * unix security, they should be running NetBSD :)
- * This allows userspace tasks to extend system calls. The user provided
- * function uses the same semantics as Xisop syscall ones. An int value
- * can be returned, which will then be returned by sys_custom(), and
- * arbitrary data may be written into the supplied results pointer if wanted
- * (the first void * argument, which is set to the supplied res pointer).
- * The user function can obtain it's arguments from the second void *,
- * which is supplied using args. This way possibilities are endless.
- */
-void sys_custom(void *res, void (*func)(void *, void *), void *args)
-{
-    struct _sargs {
-       void (*func)(void *, void *);
-       void *args;
-    } sargs = {
-       func,
-       args
-    };
-
-    _syscall(SYS_CUSTOM, res, &sargs);
-}
diff --git a/Xisop/src/common/kernel/syscall.h b/Xisop/src/common/kernel/syscall.h
deleted file mode 100644 (file)
index 639a0c5..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* $Id: syscall.h,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERN_SYSCALL_H
-#define KERN_SYSCALL_H
-
-
-
-#include <common/types.h>
-#include <common/kernel/exception.h>
-#include <common/kernel/memory.h>
-
-
-
-/* Currently available syscalls */
-enum syscalls {
-    SYS_GETROOT = 0,
-    SYS_INT_DISABLE,
-    SYS_INT_ENABLE,
-    SYS_IDLE,
-    SYS_CUSTOM,
-    SYS_MAX
-};
-
-
-
-void syscall_init(void);
-void _scatch(u_int32_t, void *, void *);
-
-struct xisop_root *sys_getroot(void);
-void sys_int_disable(void);
-void sys_int_enable(void);
-void sys_idle(void);
-void sys_custom(void *, void (*)(void *, void *), void *);
-
-
-
-extern void (*_syscalls[])(void *, void *);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernel/task.c b/Xisop/src/common/kernel/task.c
deleted file mode 100644 (file)
index 0234078..0000000
+++ /dev/null
@@ -1,432 +0,0 @@
-/* $Id: task.c,v 1.8 2004/06/04 02:15:47 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/task.h>
-#include <common/kernel/port.h>
-#include <common/kernel/main.h>
-#include <common/kernel/scheduler.h>
-#include <common/kernel/object.h>
-#include <common/kernel/statistic.h>
-#include <common/kernel/debug.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/syscall.h>
-#include <port/support.h>
-#include <processor/support.h>
-
-
-
-static void task_startend_code(void);
-
-static int task_reaper(void *, void *);
-
-
-
-task_t *task_alloc(int (*start)(void *, void *), void *res, void *args,
-       priority_t priority, size_t stacksize, u_int8_t flags)
-{
-    if (start != NULL && stacksize != 0) {
-       register page_t *stack = NULL;
-       register u_int32_t pages;
-
-       pages = stacksize / _PAGE_SIZE;
-       if (stacksize % _PAGE_SIZE)
-           pages++;
-       if ((stack = pages_alloc(0, pages, FALSE)) != NULL) {
-           register task_t *task = NULL;
-
-           if ((task = (task_t *)spool_alloc(POOL_TASK)) != NULL) {
-               if ((flags & TF_SHARED) != 0) {
-                   register mpool_t *mpool = CURTASK()->mpool;
-
-                   if (OBJECT_VALID(mpool, OBJECT_MPOOL)) {
-                       /* This task will share mpool_t with parent */
-                       lock_acquire(&mpool->lock);
-                       mpool->shared = TRUE;
-                       mpool->usecount++;
-                       task->mpool = mpool;
-                       _lock_release(&mpool->lock);
-                   }
-               } else {
-                   /* This task needs it's own unique mpool_t */
-                   if ((task->mpool = (mpool_t *)spool_alloc(POOL_MPOOL))
-                           != NULL) {
-                       if (!mpool_init(task->mpool))
-                           task->mpool = (mpool_t *)spool_free(POOL_MPOOL,
-                                   (pnode_t *)task->mpool);
-                   }
-               }
-               if (task->mpool != NULL) {
-                   /* Validate task_t object */
-                   OBJECT_VALIDATE(task, OBJECT_TASK);
-                   /* Initialize other task_t fields */
-                   task->sleepflags = 0;
-                   task->flags = flags;
-                   task->state = STATE_START;
-                   task->priority = priority;
-                   task->sigalloc = task->sigwait = task->sigrecv = 0;
-                   task->start = start;
-                   task->res = res;
-                   task->args = args;
-                   task->rescode = 0;
-                   task->stack = stack;
-                   task->stacksize = pages * _PAGE_SIZE;
-                   _ctx_init(&task->ctx, (u_int32_t *)stack->address,
-                           task->stacksize, (void *)task_startend_code);
-                   /* Resources */
-                   DLIST_INIT(&task->resources.ports);
-                   DLIST_INIT(&task->resources.devices);
-                   task->resources.device = NULL;
-                   STAT(STAT_TASKS_ALLOC, 1);
-
-                   return task;
-               } else {
-                   STAT(STAT_TASKS_ALLOC_NOMEM, 1);
-                   DEBUG_PRINTF(
-                   "* %T task_alloc(%p. %p, %p, %d, %u, %x) - mpool_init()\n",
-                       start, res, args, (int32_t)priority, stacksize,
-                       (u_int32_t)flags);
-               }
-               spool_free(POOL_TASK, (pnode_t *)task);
-           } else {
-               STAT(STAT_TASKS_ALLOC_NOMEM, 1);
-               DEBUG_PRINTF(
-               "* %T task_alloc(%p, %p, %p, %d, %u, %x) - Out of memory\n",
-                       start, res, args, (int32_t)priority, stacksize,
-                       (u_int32_t)flags);
-           }
-           pages_free(stack);
-       } else {
-           STAT(STAT_TASKS_ALLOC_NOMEM, 1);
-           DEBUG_PRINTF(
-               "* %T task_alloc(%p, %p, %p, %d, %u, %x) - Out of memory\n",
-               start, res, args, (int32_t)priority, stacksize,
-               (u_int32_t)flags);
-       }
-    } else {
-       STAT(STAT_TASKS_ALLOC_FAILED, 1);
-       DEBUG_PRINTF("* %T task_alloc(%p, %p, %p, %d, %u, %x)\n",
-               start, res, args, (int32_t)priority, stacksize,
-               (u_int32_t)flags);
-    }
-
-    return NULL;
-}
-
-
-/* Free a task_t. Also unlinks the task from the system lists. The task
- * must first have been processed by task_end() and thus moved into the
- * dead queue.
- */
-task_t *task_free(task_t *task)
-{
-    if (OBJECT_VALID(task, OBJECT_TASK) &&
-           (task->state == STATE_DEAD || task->state == STATE_START)) {
-       SCHED_DISABLE();
-       if (task->state == STATE_DEAD)
-           DLIST_UNLINK(&root->tasks_dead, (node_t *)task);
-       SCHED_ENABLE();
-       if (task->stack != NULL)
-           pages_free(task->stack);
-       /* Free task resources */
-       /* All ports the task created. Linked via port_t->tasknode. */
-       {
-           register port_t *port, *next;
-
-           for (port = DLIST_TOP(&(task->resources.ports)); port != NULL;
-                   port = next) {
-               next = DLIST_NEXT(&port->tasknode);
-               port_destroy((port_t *)&(((hashnode_t *)port)[-1]));
-           }
-       }
-       /* Devices we opened. Linked via device_t->tasknode. */
-       {
-           register node_t *node, *next;
-
-           for (node = DLIST_TOP(&(task->resources.devices)); node != NULL;
-                   node = next) {
-               next = DLIST_NEXT(node);
-               device_close((device_t *)&(((pnode_t *)node)[-1]));
-           }
-       }
-       /* If we are a device */
-       if (task->resources.device)
-           device_detach(task->resources.device);
-       /* XXX other future resources handling, like opened libraries, etc */
-       /* Invalidate task */
-       OBJECT_INVALIDATE(task);
-       /* All memory the task allocated using malloc(). If mpool_destroy()
-        * fails with FALSE, either a problem occured or the mpool_t is still
-        * in use by another task sharing it, in which case we do not free it.
-        */
-       if (mpool_destroy(task->mpool))
-           spool_free(POOL_MPOOL, (pnode_t *)task->mpool);
-       /* And finally the task node itself. */
-       spool_free(POOL_TASK, (pnode_t *)task);
-       STAT(STAT_TASKS_FREE, 1);
-    } else {
-       STAT(STAT_TASKS_FREE_FAILED, 1);
-       DEBUG_PRINTF("* %T task_free(%p)\n", task);
-    }
-
-    return NULL;
-}
-
-
-/* Allows to start a new task */
-bool task_start(task_t *task)
-{
-    bool ok = FALSE;
-
-    if (OBJECT_VALID(task, OBJECT_TASK) && task->state == STATE_START) {
-       /* This task was just allocated, start it */
-       task->state = STATE_READY;
-       if ((task->credits = task->priority) == -128)
-           task->credits++;
-       SCHED_DISABLE();
-       DLIST_APPEND(&root->tasks_ready, (node_t *)task);
-       SCHED_ENABLE();
-       ok = TRUE;
-       STAT(STAT_TASKS_STARTED, 1);
-    } else {
-       STAT(STAT_TASKS_STARTED_FAILED, 1);
-       DEBUG_PRINTF("* %T task_start(%p)\n", task);
-    }
-
-    return ok;
-}
-
-
-bool task_end(task_t *task)
-{
-    bool ok = FALSE, current = FALSE;
-
-    if (OBJECT_VALID(task, OBJECT_TASK) && task->state != STATE_DEAD) {
-       ok = TRUE;
-       SCHED_DISABLE();
-       switch (task->state) {
-       case STATE_RUN:
-           /* FALLTHROUGH */
-       case STATE_READY:
-           DLIST_SWAP(&root->tasks_dead, &root->tasks_ready, (node_t *)task,
-                   FALSE);
-           break;
-       case STATE_WAIT:
-           DLIST_SWAP(&root->tasks_dead, &root->tasks_wait, (node_t *)task,
-                   FALSE);
-           break;
-       default:
-           ok = FALSE;
-           break;
-       }
-       if (ok) {
-           STAT(STAT_TASKS_ENDED, 1);
-           task->state = STATE_DEAD;
-           /* Wakeup reaper as there's at least one task on the dead queue */
-           task_wakeup(root->task_reaper, TSF_KERNEL);
-           /* If it's the current task, ensure to yield now. */
-           if (task == root->curtask)
-               current = TRUE;
-       }
-       SCHED_ENABLE();
-    }
-
-    if (current) {
-       /* We also probably could go to sleep indefinitely instead,
-        * but as we are in the dead queue, we are certain that we will not
-        * be given another chance to run until we get freed.
-        */
-       for (;;)
-           _yield(NULL);
-    }
-    if (!ok) {
-       STAT(STAT_TASKS_ENDED_FAILED, 1);
-       DEBUG_PRINTF("* %T task_end(%p)\n", task);
-    }
-
-    return ok;
-}
-
-
-priority_t task_getpriority(task_t *task)
-{
-    register priority_t p = 0;
-
-    if (OBJECT_VALID(task, OBJECT_TASK))
-       p = task->priority;
-
-    return p;
-}
-
-
-priority_t task_setpriority(task_t *task, priority_t new)
-{
-    register priority_t p = 0;
-
-    if (OBJECT_VALID(task, OBJECT_TASK)) {
-       SCHED_DISABLE();
-       p = task->priority;
-       task->priority = new;
-       if ((task->credits = new) == -128)
-           task->credits++;
-       SCHED_ENABLE();
-    }
-
-    return p;
-}
-
-
-/* This is the code which each new task automatically starts executing, which
- * performs some initializations and then executes the task-specific code.
- * It also takes control again when the task ends and returns.
- */
-static void task_startend_code(void)
-{
-    register task_t *task = CURTASK();
-
-    /* XXX Setup our reserved signals and port */
-
-    /* Call the supplied entry point function */
-    task->rescode = task->start(task->res, task->args);
-
-    /* Adios amigo! Translation: KTHXBYE!111 */
-    task_end(task);
-    /* NOTREACHED */
-}
-
-
-
-/* System tasks
- * ============
- */
-
-/* This consists of Xisop init task. It's purpose is to launch the system
- * tasks as well as all tasks which the port-specific code defined which should
- * be launched. We also link in system and port-defined shared libraries.
- * Resident devices and handlers actually consist of tasks and are given
- * no special treatment.
- */
-/* ARGSUSED */
-int task_init(void *res, void *args)
-{
-    /* Register ourself */
-    root->task_init = CURTASK();
-
-    /* Attach system shared libraries */
-    {
-       /* XXX */
-    }
-
-    /* Launch system tasks, which auto-register themselves by storeing their
-     * address in the Xisop root structure.
-     */
-    {
-       register task_t *task;
-
-       /* Task reaper */
-       if ((task = task_alloc(task_reaper, NULL, NULL, 0, 4096,
-                       TF_KERNEL | TF_SHARED)) != NULL)
-           task_start(task);
-    }
-
-    /* Attach port-specified shared libraries and launch port-specific tasks */
-    _port_init();
-
-    /* And perform our init task shores, which are neverending. */
-    {
-       port_t *pubport;
-
-       if ((pubport = port_create("INIT")) != NULL) {
-           port_t *ports[] = {
-               pubport
-           };
-           register message_t *msg;
-
-           /* Currently just reply to any message we get and do nothing */
-           for (;;) {
-               if ((port_wait(ports, 1, NULL)) == pubport) {
-                   while ((msg = port_get(pubport)) != NULL)
-                       port_reply(msg);
-               }
-           }
-       }
-    }
-
-    /* XXX We actually could safely die here for now, but don't want to.
-     * Eventually we will make sure that the tasks remain running, and
-     * restart tasks which are marked to be persistant if they ever die.
-     */
-    /* NOTREACHED */
-    return 0;
-}
-
-
-/* This consists of the reaper task, which is started by Xisop init task.
- * Our duty consists of sleeping, but to free the tasks which are on the
- * dead queue, if any, when wakeing up. The only event which awakes us up
- * consists of the task_end() function. As tasks may have alot of resources
- * to free back to the system, it is a good idea to have this task dedicating
- * it's own CPU time to do it, it releives all other tasks, as well as the
- * kernel from having to.
- */
-/* ARGSUSED */
-static int task_reaper(void *res, void *args)
-{
-    /* Register ourselves for task_end() */
-    root->task_reaper = CURTASK();
-
-    for (;;) {
-       task_sleep(CURTASK(), TSF_KERNEL, NULL);
-       /* We were awaken by task_end() */
-       for (;;) {
-           register task_t *task;
-
-           SCHED_DISABLE();
-           task = DLIST_TOP(&root->tasks_dead);
-           SCHED_ENABLE();
-           if (task != NULL) {
-               /* Free this task and let some CPU time to others */
-               task_free(task);
-               _yield(NULL);
-           } else
-               break;
-       }
-    }
-
-    /* NOTREACHED */
-    return 0;
-}
diff --git a/Xisop/src/common/kernel/task.h b/Xisop/src/common/kernel/task.h
deleted file mode 100644 (file)
index ea9f069..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/* $Id: task.h,v 1.2 2004/01/19 18:07:11 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNEL_TASK_H
-#define KERNEL_TASK_H
-
-
-
-#include <common/types.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/signal.h>
-#include <common/kernel/port.h>
-#include <common/kernel/device.h>
-#include <common/kernlib/string.h>
-#include <common/kernlib/list.h>
-#include <processor/support.h>
-/*#include <kern/handler.h>    XXX I must be able to include this!*/
-
-
-
-/* Useful macro to be used in kernel code */
-#define CURTASK()              (root->curtask)
-
-
-
-/* task.state */
-#define STATE_START            0
-#define STATE_READY            1
-#define STATE_WAIT             2
-#define STATE_DEAD             3       /* To be removed */
-#define STATE_RUN              4
-
-/* task.flags and tn_message.event */
-#define TF_KERNEL              (1 << 0)        /* Kernelspace task */
-#define TF_SYSTEM              (1 << 1)        /* A system task */
-#define TF_DEVICE              (1 << 2)        /* Task is a device */
-#define TF_HANDLER             (1 << 3)        /* Task is a handler */
-#define TF_OS                  (1 << 4)        /* OS resident task */
-#define TF_SHARED              (1 << 5)        /* Shares mpool_t w/ parent */
-
-/* some defined values for task.priority */
-#define PRI_MAX                        127     /* highest priority */
-#define PRI_DEFAULT            0       /* default priority for normal tasks */
-#define PRI_MIN                        -127    /* lowest priority */
-
-
-
-/* Task's allocated resources */
-struct resources {
-    list_t ports;              /* Linked via port_t->tasknode */
-    list_t devices;            /* Linked via device_t->tasknode */
-    devicenode_t *device;      /* If we are a device */
-    /*handlernode_t *handler;*/        /* If we are a handler */
-};
-
-/* XXX Don't know if this will be useful/required yet */
-/* These, similarly to the task's memory pool, will only be freed once the
- * parent task is freed, in case it has threads.
- * XXX hmm I think that the message ports cannot be shared among threads, since
- * they require a signal bit, allocated on the specific task!
- * now would signal shareing be wanted? several tasks would then be awaken
- * by the same signal. I doubt we want this on xisop.
- */
-/*
-struct procstate {
-       lock *currentdir;
-       lock *in;
-       lock *out;
-       lock *err;
-       struct handlerpacket pkt;
-       struct msgport *pktrp;
-};
-*/
-
-/* This is a task node, as the kernel sees it. */
-struct task {
-    /* Tasks use the primary node for swapping */
-    pnode_t node;
-    /* User multipurpose node */
-    node_t usernode;
-
-    /* Validity sceal */
-    u_int32_t object_magic;
-
-    /* Info */
-    u_int32_t sleepflags;
-    u_int8_t flags;
-    u_int8_t state;
-
-    /* Credits are given according to priority by the scheduler */
-    priority_t priority, credits;
-
-    /* Signal */
-    sigmask_t sigalloc, sigwait, sigrecv;
-    /* XXX sigfunc sighandlers[32]; */
-
-    /* Entry point and parameters/results */
-    int (*start)(void *, void *);
-    void *res, *args;
-    int rescode;
-
-    /* Context */
-    page_t *stack;
-    size_t stacksize;
-    _ctx_t ctx;
-
-    /* Memory pool, which can be shared or unique */
-    mpool_t *mpool;
-
-    /* Resources we have opened which need special handling other than
-     * freeing the memory they allocated.
-     */
-    struct resources resources;
-};
-
-
-
-task_t *task_alloc(int (*)(void *, void *), void *, void *, priority_t,
-       size_t, u_int8_t);
-task_t *task_free(task_t *);
-bool task_start(task_t *);
-bool task_end(task_t *);
-priority_t task_getpriority(task_t *);
-priority_t task_setpriority(task_t *, priority_t);
-
-int task_init(void *, void *);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernlib/clean.sh b/Xisop/src/common/kernlib/clean.sh
deleted file mode 100755 (executable)
index c8bd473..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-# $Id: clean.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ../../generic_makedefs.sh
-
-cleanlib .
-cleanlib string
-show $L_RM ar/*.a
diff --git a/Xisop/src/common/kernlib/fifo.h b/Xisop/src/common/kernlib/fifo.h
deleted file mode 100644 (file)
index 3e4cc71..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/* $Id: fifo.h,v 1.2 2004/06/04 19:03:36 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNLIB_FIFO_H
-#define KERNLIB_FIFO_H
-
-
-
-#include <common/types.h>
-
-
-
-/* Allows to create a new fifo_t type structure, to fit any data type */
-#define FIFO_DEFINE(n, o)      typedef struct n {                      \
-    o *top, *bottom, *head, *tail;                                     \
-    u_int32_t size;                                                    \
-} n
-
-FIFO_DEFINE(fifo8_t, u_int8_t);
-FIFO_DEFINE(fifo16_t, u_int16_t);
-FIFO_DEFINE(fifo32_t, u_int32_t);
-FIFO_DEFINE(fifo64_t, u_int64_t);
-
-
-
-/* Initializes a FIFO */
-#define FIFO_INIT(f, b, s)     do {                                    \
-    (f)->top = (f)->head = (f)->tail = (b);                            \
-    (f)->bottom = &((b)[(s)]);                                         \
-    (f)->size = (s) - 1;                                               \
-} while (/* CONSTCOND */0)
-
-/* Used to compute the next location of a tail or head pointer, accounting
- * for the necessary occasional rotation.
- */
-#define FIFO_NEXT(f, p)        (&((p)[1]) == (f)->bottom ? (f)->top : &((p)[1]))
-
-/* Returns TRUE if the FIFO is full, that is, cannot hold more elements */
-#define FIFO_FULL(f)           (FIFO_NEXT((f), (f)->head) == (f)->tail)
-
-/* Returns TRUE if the FIFO is empty */
-#define FIFO_EMPTY(f)          ((f)->head == (f)->tail)
-
-/* Returns the number of currently held elements into a FIFO */
-#define FIFO_STAT(f)           (FIFO_EMPTY(f) ? 0 :                    \
-       (f)->head - (f)->tail > 0 ?                                     \
-           ((f)->head - (f)->tail) / sizeof(*(f)->head):               \
-               ((f)->size - ((f)->tail - (f)->head)) / sizeof(*(f)->head))
-
-#define FIFO_AVAIL(f)          ((f)->size - FIFO_STAT(f))
-
-#define FIFO_FLUSH(f)          ((f)->tail = (f)->head)
-
-/* If no available room the oldest element is lost. The caller may verify
- * with FIFO_FULL() first if needed.
- */
-#define FIFO_PUT(f, e)         do {                                    \
-    *(f)->head = *(e);                                                 \
-    (f)->head = FIFO_NEXT((f), (f)->head);                             \
-    if (FIFO_EMPTY(f))                                                 \
-       (f)->tail = FIFO_NEXT((f), (f)->tail);                          \
-} while (/* CONSTCOND */0)
-
-/* Has no action if the buffer has no more elements, but does not return any
- * result to say so. The caller may use FIFO_EMPTY() to check if needed.
- */
-#define FIFO_GET(f, e)         do {                                    \
-    if (!FIFO_EMPTY(f)) {                                              \
-       *(e) = *(f)->tail;                                              \
-       (f)->tail = FIFO_NEXT((f), (f)->tail);                          \
-    }                                                                  \
-} while (/* CONSTCOND */0)
-
-#define FIFO_FIND(f, p, e)     do {                                    \
-    register typeof(*(e)) *r;                                          \
-                                                                       \
-    *(p) = NULL;                                                       \
-    for (r = (f)->tail; r != (f)->head; r = FIFO_NEXT(f, r))           \
-       if (*r == *(e)) {                                               \
-           *(p) = r;                                                   \
-           break;                                                      \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-/* XXX Those are bugged for now */
-#define FIFO_ALLOC(f, p, a, s) do {                                    \
-    register int r;                                                    \
-                                                                       \
-    if ((r = (f)->tail - (f)->head) != 0) {                            \
-       if (r < 1)                                                      \
-           r = (f)->bottom - (f)->head;                                \
-       if ((r /= sizeof(*(f)->head)) > (int)(s))                       \
-           r = (int)(s);                                               \
-       *(p) = (f)->head;                                               \
-       (f)->head = (&((f)->head[r]) == (f)->bottom ? (f)->top :        \
-           &((f)->head[r]));                                           \
-    }                                                                  \
-    *(a) = (size_t)r;                                                  \
-} while (/* CONSTCOND */0)
-
-#define FIFO_FREE(f, p, a, s)  do {                                    \
-    register int r;                                                    \
-                                                                       \
-    if ((r = (f)->head - (f)->tail) != 0) {                            \
-       if (r < 1)                                                      \
-           r = (f)->bottom - (f)->tail;                                \
-       if ((r /= sizeof(*(f)->tail)) > (int)(s))                       \
-           r = (int)(s);                                               \
-       *(p) = (f)->tail;                                               \
-       (f)->tail = (&((f)->tail[r]) == (f)->bottom ? (f)->top :        \
-           &((f)->tail[r]));                                           \
-    }                                                                  \
-    *(a) = (size_t)r;                                                  \
-} while (/* CONSTCOND */0)
-
-#define FIFO_WRITE(f, p, a, s) do {                                    \
-    /* XXX */                                                          \
-} while (/* CONSTCOND */0)
-
-#define FIFO_READ(f, p, a, s)  do {                                    \
-    /* XXX */                                                          \
-} while (/* CONSTCOND */0)
-
-
-
-size_t getnfifo8(u_int8_t *, fifo8_t *, size_t);
-size_t putnfifo8(fifo8_t *, u_int8_t *, size_t);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernlib/hash.c b/Xisop/src/common/kernlib/hash.c
deleted file mode 100644 (file)
index c652405..0000000
+++ /dev/null
@@ -1,381 +0,0 @@
-/* $Id: hash.c,v 1.6 2004/06/04 02:15:47 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/debug.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/object.h>
-#include <common/kernlib/list.h>
-#include <common/kernlib/hash.h>
-
-
-
-/* This system is safe to use 32-bit hashes internally, despite the possibility
- * for collisions. We maintain an array or buckets, within which the entries
- * are distributed. A 32-bit hash collision entry will end up on the same
- * bucket. We however also make sure to not allow to store exact duplicate
- * keys. The number if buckets will increase and decrease whenever the system
- * detects that it becomes necessary for efficiency. The larger the number of
- * buckets, the less nodes are likely to coexist in each bucket. The bucket
- * index to use is evaluated using a modulo to convert the 32-bit hash to
- * fit into the current number of buckets in the table. Of course, when
- * the number of buckets is to be updated (which ideally happens rarely),
- * the entries are rehashed to be properly indexed within the new capacity.
- *
- * The number of buckets is automatically doubled when the table fills up
- * at a factor of 1. This way, we avoid having to calculate a fill factor
- * using floating point arithmetic. Commonly used value for the initial hash
- * table bucket capacity is 16, which are set HT_DEFAULT_CAPACITY represents.
- *
- * Searching for a key by pattern, which requires iterating through the
- * nodes, rather than through it's absolute key can actually be a little
- * slower than running through a simple linked list of absolute hash values,
- * since all buckets must be scanned. However, we ensure to stop running
- * through buckets when the total number of mappings have been scanned already.
- * Lookups using the absolute key of the node will be much faster in the case
- * where the hash table grows considerably, however.
- */
-
-
-
-#define HASH_INDEX(h, s)       ((h) % (s))
-
-
-
-static void hashtable_rehash(hashtable_t *, unsigned int);
-
-
-
-bool hashtable_init(hashtable_t *t, const char *label,
-       unsigned int initialcapacity, void *(*allocfunc)(size_t),
-       void (*freefunc)(void *),
-       int (*keycomp)(const void *, const void *, size_t),
-       u_int32_t (*keyhash)(const void *, size_t), bool dynamic)
-{
-    if (!OBJECT_VALID(t, OBJECT_HASHTABLE)) {
-       if ((t->array = allocfunc(sizeof(list_t) * initialcapacity)) != NULL) {
-           unsigned int i;
-
-           OBJECT_VALIDATE(t, OBJECT_HASHTABLE);
-           t->label = label;
-           t->malloc = allocfunc;
-           t->free = freefunc;
-           t->keycomp = keycomp;
-           t->keyhash = keyhash;
-           t->nodes = 0;
-           t->initial = t->capacity = initialcapacity;
-           t->avgtotal = t->avgcnt = initialcapacity;
-           t->dynamic = dynamic;
-           t->iterating = FALSE;
-           for (i = 0; i < initialcapacity; i++)
-               DLIST_INIT(&(t->array[i]));
-
-           return TRUE;
-       } else
-           DEBUG_PRINTF("* %T hashtable_init(%p = %s) - malloc(%d)\n",
-                   label, t, (int)sizeof(list_t) * initialcapacity);
-    } else
-       DEBUG_PRINTF(
-               "* %T hashtable_init(%p = %s) - Table already initialized",
-               label, t);
-
-    return FALSE;
-}
-
-
-void hashtable_destroy(hashtable_t *t, bool freeall)
-{
-    if (OBJECT_VALID(t, OBJECT_HASHTABLE)) {
-       if (t->array != NULL) {
-           if (freeall) {
-               register unsigned int i, done;
-               register list_t *l;
-               register hashnode_t *k, *kt;
-
-               for (i = done = 0; done < t->nodes && i < t->capacity; i++) {
-                   l = &(t->array[i]);
-                   if (DLIST_NODES(l) > 0) {
-                       for (k = DLIST_TOP(l); k != NULL; k = kt) {
-                           kt = DLIST_NEXT(k);
-                           pool_free((pnode_t *)k);
-                           done++;
-                       }
-                   }
-               }
-           }
-           t->free(t->array);
-       }
-       OBJECT_INVALIDATE(t);
-    } else
-       DEBUG_PRINTF(
-               "* %T hashtable_destroy(%p) - Invalid hashtable_t pointer",
-               t);
-}
-
-
-hashnode_t *hashtable_lookup(hashtable_t *t, const void *key, size_t keysize)
-{
-    register u_int32_t hash;
-    register unsigned int i;
-    register list_t *l;
-    register hashnode_t *k = NULL;
-
-    if (OBJECT_VALID(t, OBJECT_HASHTABLE)) {
-       hash = t->keyhash(key, keysize);
-       i = HASH_INDEX(hash, t->capacity);
-       l = &(t->array[i]);
-       if (DLIST_NODES(l) > 0) {
-           DLIST_FOREACH(l, k) {
-               if (k->hash == hash && k->keysize == keysize &&
-                       t->keycomp(k->key, key, keysize) == 0)
-                   break;
-           }
-       }
-    } else
-       DEBUG_PRINTF(
-               "* %T hashtable_lookup(%p) - Invalid hashtable_t pointer",
-               t);
-
-    return k;
-}
-
-
-bool hashtable_link(hashtable_t *t, hashnode_t *k, const void *key,
-       size_t keysize, bool check)
-{
-    register u_int32_t hash;
-    register unsigned int i;
-    register list_t *l;
-    bool ok = TRUE;
-
-    if (!OBJECT_VALID(t, OBJECT_HASHTABLE)) {
-       DEBUG_PRINTF("* %T hashtable_link(%p) - Invalid hashtable_t pointer",
-               t);
-       return FALSE;
-    }
-    if (k == NULL) {
-       DEBUG_PRINTF(
-               "* %T hashtable_link(NULL) - Table (%p = %s) Invalid "
-               "hashnode_t pointer",
-               t, t->label);
-       return FALSE;
-    }
-
-    hash = t->keyhash(key, keysize);
-    i = HASH_INDEX(hash, t->capacity);
-    l = &(t->array[i]);
-    if (check) {
-       /* We do not allow exact duplicates, so verify first. Duplicate
-        * hashes are fine, however, as long as the key data is not identical.
-        */
-       if (DLIST_NODES(l) > 0) {
-           register hashnode_t *tk;
-
-           DLIST_FOREACH(l, tk) {
-               if (tk == k || (tk->hash == hash && tk->keysize == keysize &&
-                           t->keycomp(tk->key, key, keysize) == 0)) {
-                   DEBUG_PRINTF(
-                           "* %T hashtable_link(%p = %s, %p) - Duplicate key "
-                           "insert attempt", t, t->label, k);
-                   ok = FALSE;
-                   break;
-               }
-           }
-       }
-    }
-    if (ok) {
-       OBJECT_VALIDATE(k, OBJECT_HASHNODE);
-       k->hash = hash;
-       k->list = l;
-       k->key = key;
-       k->keysize = keysize;
-       DLIST_INSERT(l, (node_t *)k);
-       /* Grow capacity if necessary */
-       t->nodes++;
-       if (t->dynamic && !t->iterating) {
-           if (t->dynamic && !t->iterating)
-               hashtable_rehash(t, t->capacity * 2);
-       }
-    }
-
-    return ok;
-}
-
-
-void hashtable_unlink(hashtable_t *t, hashnode_t *k)
-{
-    if (OBJECT_VALID(t, OBJECT_HASHTABLE)) {
-       if (OBJECT_VALID(k, OBJECT_HASHNODE)) {
-           unsigned int exceeding;
-
-           OBJECT_INVALIDATE(k);
-           DLIST_UNLINK(k->list, (node_t *)k);
-           k->list = NULL;
-           t->nodes--;
-
-           /* Verify if the capacity should be reduced, using statistics */
-           t->avgtotal += t->capacity;
-           t->avgcnt++;
-           if (t->avgcnt > t->capacity / (t->initial * 3)) {
-               t->avgcnt = 1;
-               t->avgtotal = t->capacity;
-           }
-           /* Rehash with a smaller capacity if necessary */
-           if (t->dynamic && !t->iterating) {
-               if ((exceeding = t->capacity - (t->avgtotal / t->avgcnt)) > 0)
-                   hashtable_rehash(t, t->capacity - exceeding);
-           }
-       } else
-           DEBUG_PRINTF(
-                   "* %T hashtable_unlink(%p) - Table (%p = %s) Invalid "
-                   "hashnode_t pointer",
-                   k, t, t->label);
-    } else
-       DEBUG_PRINTF(
-               "* %T hashtable_unlink(%p) - Invalid hashtable_t pointer",
-               t);
-}
-
-
-/* Note that as the user generally has a pool_t dedicated to the hashnode_t
- * elements for a particular table, it may be more efficient to not use
- * the <freeall> option and to pool_free() which does not need to iterate
- * through nodes. This function has to however, because it obviously cannot
- * assume that the caller wishes to free all nodes of the origin pool_t, or
- * that all entries origin from the same pool_t.
- */
-void hashtable_empty(hashtable_t *t, bool freeall)
-{
-    register unsigned int i;
-    register list_t *l;
-    register hashnode_t *k, *kt;
-
-    if (OBJECT_VALID(t, OBJECT_HASHTABLE)) {
-       if (freeall) {
-           for (i = 0; i < t->capacity; i++) {
-               l = &(t->array[i]);
-               if (DLIST_NODES(l) > 0) {
-                   for (k = DLIST_TOP(l); k != NULL; k = kt) {
-                       kt = DLIST_NEXT(k);
-                       pool_free((pnode_t *)k);
-                   }
-               }
-           }
-       } else {
-           for (i = 0; i < t->capacity; i++)
-               DLIST_INIT(&(t->array[i]));
-       }
-       if (t->dynamic && !t->iterating)
-           hashtable_rehash(t, t->initial);
-    } else
-       DEBUG_PRINTF(
-               "* %T hashtable_empty(%p) - Invalid hashtable_t pointer",
-               t);
-}
-
-
-void hashtable_iterate(hashtable_t *t,
-       bool (*func)(hashnode_t *, void *), void *udata)
-{
-    register unsigned int i;
-    register list_t *l;
-    register hashnode_t *k, *kt;
-
-    if (OBJECT_VALID(t, OBJECT_HASHTABLE)) {
-       if (t->nodes > 0) {
-           t->iterating = TRUE;
-           for (i = 0; i < t->capacity; i++) {
-               l = &(t->array[i]);
-               if (DLIST_NODES(l) > 0) {
-                   /* Note that we use a temporary variable to hold the next
-                    * key, in case the user function alters the key node
-                    * (i.e. unlinks it)
-                    */
-                   for (k = DLIST_TOP(l); k != NULL; k = kt) {
-                       kt = DLIST_NEXT(k);
-                       if (!func(k, udata)) {
-                           t->iterating = FALSE;
-                           return;
-                       }
-                   }
-               }
-           }
-           t->iterating = FALSE;
-       }
-    } else
-       DEBUG_PRINTF(
-               "* %T hashtable_iterate(%p) - Invalid hashtable_t pointer",
-               t);
-}
-
-
-/* Rehashes the whole hashtable so that the capacity may be changed to the
- * specified one. The memory area is also automatically changed. Ideally,
- * this only occurs rarely. If it fails because of a lack of memory, the
- * hash table will simply not be affected, but lookups will become slower.
- */
-static void hashtable_rehash(hashtable_t *t, unsigned int newcapacity)
-{
-    list_t *newarray;
-
-    if ((newarray = t->malloc(sizeof(list_t) * newcapacity)) != NULL) {
-       register unsigned int i, done;
-
-       for (i = 0; i < newcapacity; i++)
-           DLIST_INIT(&newarray[i]);
-
-       for (i = done = 0; done < t->nodes && i < t->capacity; i++) {
-           register hashnode_t *k, *kt;
-           register list_t *l, *newl;
-
-           l = &(t->array[i]);
-           if (DLIST_NODES(l) > 0) {
-               for (k = DLIST_TOP(l); k != NULL; k = kt) {
-                   kt = DLIST_NEXT(k);
-                   newl = &newarray[HASH_INDEX(k->hash, newcapacity)];
-                   DLIST_SWAP(newl, l, (node_t *)k, TRUE);
-                   k->list = newl;
-                   done++;
-               }
-           }
-       }
-
-       t->capacity = newcapacity;
-       t->free(t->array);
-       t->array = newarray;
-    }
-}
diff --git a/Xisop/src/common/kernlib/hash.h b/Xisop/src/common/kernlib/hash.h
deleted file mode 100644 (file)
index ed04553..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* $Id: hash.h,v 1.5 2004/06/04 02:15:47 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNLIB_HASH_H
-#define KERNLIB_HASH_H
-
-
-
-#include <common/types.h>
-#include <common/kernel/memory.h>
-#include <common/kernlib/list.h>
-
-
-
-struct hashnode {
-    pnode_t node;
-    u_int32_t object_magic, hash;
-    list_t *list;
-    const void *key;
-    size_t keysize;
-    /* Custom user data will follow, uncluding the key element to which the
-     * previous key pointer is expected to point.
-     */
-};
-
-struct hashtable {
-    pnode_t node;      /* In case we want a pool_t of hashtable_t */
-    u_int32_t object_magic;
-    unsigned int initial, capacity, nodes;
-    const char *label;
-    list_t *array;
-    void *(*malloc)(size_t);
-    void (*free)(void *);
-    int (*keycomp)(const void *, const void *, size_t);
-    u_int32_t (*keyhash)(const void *, size_t);
-    unsigned int avgtotal, avgcnt;
-    bool dynamic, iterating;
-};
-
-
-
-#define HT_DEFAULT_CAPACITY    16
-
-#define HASHTABLE_NODES(t)     ((t)->nodes)
-
-
-
-bool hashtable_init(hashtable_t *, const char *, unsigned int,
-       void *(*)(size_t), void (*)(void *),
-       int (*)(const void *, const void *, size_t),
-       u_int32_t (*)(const void *, size_t), bool);
-void hashtable_destroy(hashtable_t *, bool);
-hashnode_t *hashtable_lookup(hashtable_t *, const void *, size_t);
-bool hashtable_link(hashtable_t *, hashnode_t *, const void *, size_t, bool);
-void hashtable_unlink(hashtable_t *, hashnode_t *);
-void hashtable_empty(hashtable_t *, bool);
-void hashtable_iterate(hashtable_t *, bool (*)(hashnode_t *, void *),
-       void *);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernlib/lifo.h b/Xisop/src/common/kernlib/lifo.h
deleted file mode 100644 (file)
index ae9e260..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/* $Id: lifo.h,v 1.3 2004/06/04 19:14:07 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNLIB_LIFO_H
-#define KERNLIB_LIFO_H
-
-
-
-#include <common/types.h>
-
-
-
-/* LIFO_DEFINE(lifotypename, objecttype); */
-#define LIFO_DEFINE(n, o)      typedef struct n {                      \
-    u_int32_t size, elements;                                          \
-    o *buffer, *endbuffer, *head;                                      \
-} n
-
-/* Because of the way this is implemented using macros, it would also be
- * possible to provide lifo types to hold structures.
- */
-LIFO_DEFINE(lifo8_t, u_int8_t);
-LIFO_DEFINE(lifo16_t, u_int16_t);
-LIFO_DEFINE(lifo32_t, u_int32_t);
-LIFO_DEFINE(lifo64_t, u_int64_t);
-
-
-
-/* XXX Although it's great to use macros for these operations, it also
- * prevents assembly functions to be provided to replace them.
- */
-/* void LIFO_INIT(lifo*_t *, u_int*_t *, u_int32_t); */
-#define LIFO_INIT(f, b, s)     do {                                    \
-    (f)->size = (s);                                                   \
-    (f)->elements = 0;                                                 \
-    (f)->buffer = (f)->endbuffer = (f)->head = (b);                    \
-} while (/* CONSTCOND */0)
-
-/* bool LIFO_FULL(lifo*_t *); */
-#define LIFO_FULL(f)   ((f)->elements == (f)->size)
-
-/* u_int32_t LIFO_STAT(lifo*_t *); */
-#define LIFO_STAT(f)   ((f)->elements)
-
-/* void LIFO_FLUSH(lifo*_t *); */
-#define LIFO_FLUSH(f)  do {                                            \
-    (f)->head = (f)->buffer;                                           \
-    (f)->elements = 0;                                                 \
-} while (/* CONSTCOND */0)
-
-/* void LIFO_PUT(lifo*_t *, u_int*_t *); */
-#define LIFO_PUT(s, e) do {                                            \
-    if ((s)->elements < (s)->size) {                                   \
-       *((s)->head++) = *(e);                                          \
-       (s)->elements++;                                                \
-    }                                                                  \
-} while (/* CONSTCOND */0)
-
-/* void LIFO_GET(lifo*_t *, u_int*_t *); */
-#define LIFO_GET(s, e) do {                                            \
-    if ((s)->elements > 0) {                                           \
-       *(e) = *(--(s)->head);                                          \
-       (s)->elements--;                                                \
-    }                                                                  \
-} while (/* CONSTCOND */0)
-
-/* LIFO_ALLOC(lifo*_t *, u_int*_t **, size_t *); */
-
-/* LIFO_FREE(lifo*_t, u_int*_t **, size_t *); */
-
-
-
-#endif
diff --git a/Xisop/src/common/kernlib/list.h b/Xisop/src/common/kernlib/list.h
deleted file mode 100644 (file)
index ebb8bd1..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/* $Id: list.h,v 1.5 2004/06/04 19:14:07 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNEL_LIST_H
-#define KERNEL_LIST_H
-
-
-
-#include <common/types.h>
-
-
-
-typedef struct list    list_t;
-typedef struct node    node_t;
-
-
-
-struct node {
-    node_t *prev, *next;
-};
-
-struct list {
-    node_t *top, *bottom;
-    u_int32_t nodes;
-};
-
-
-
-/* Some macros to optimize operations on doubly linked lists */
-#define DLIST_INITIALIZER      {NULL, NULL, 0}
-
-#define DLIST_INIT(lst)                do {                                    \
-    (lst)->top = (lst)->bottom = NULL;                                 \
-    (lst)->nodes = 0;                                                  \
-} while (/* CONSTCOND */0)
-
-#define DLIST_UNLINK(lst, nod) do {                                    \
-    register node_t *prev = (nod)->prev, *next = (nod)->next;          \
-                                                                       \
-    if (prev != NULL)                                                  \
-       prev->next = next;                                              \
-    else                                                               \
-       (lst)->top = next;                                              \
-    if (next != NULL)                                                  \
-       next->prev = prev;                                              \
-    else                                                               \
-       (lst)->bottom = prev;                                           \
-    (lst)->nodes--;                                                    \
-} while (/* CONSTCOND */0)
-
-#define DLIST_APPEND(lst, nod) do {                                    \
-    register node_t *tmp = (lst)->bottom;                              \
-                                                                       \
-    if (tmp != NULL) {                                                 \
-       tmp->next = (nod);                                              \
-       (nod)->prev = tmp;                                              \
-       (nod)->next = NULL;                                             \
-       (lst)->bottom = (nod);                                          \
-    } else {                                                           \
-       (lst)->bottom = (lst)->top = (nod);                             \
-       (nod)->next = (nod)->prev = NULL;                               \
-    }                                                                  \
-    (lst)->nodes++;                                                    \
-} while (/* CONSTCOND */0)
-
-#define DLIST_INSERT(lst, nod) do {                                    \
-    register node_t *tmp = (lst)->top;                                 \
-                                                                       \
-    if (tmp != NULL) {                                                 \
-       tmp->prev = (nod);                                              \
-       (nod)->prev = NULL;                                             \
-       (nod)->next = tmp;                                              \
-       (lst)->top = (nod);                                             \
-    } else {                                                           \
-       (lst)->top = (lst)->bottom = (nod);                             \
-       (nod)->next = (nod)->prev = NULL;                               \
-    }                                                                  \
-    (lst)->nodes++;                                                    \
-} while (/* CONSTCOND */0)
-
-#define DLIST_INSERTAT(lst, atnode, nod) do {                          \
-    register node_t *prev = (atnode)->prev, *next = (atnode);          \
-                                                                       \
-    (nod)->next = next;                                                        \
-    next->prev = (nod);                                                        \
-    if (prev != NULL) {                                                        \
-       prev->next = (nod);                                             \
-       (nod)->prev = prev;                                             \
-    } else {                                                           \
-       (lst)->top = (nod);                                             \
-       (nod)->prev = NULL;                                             \
-    }                                                                  \
-    (lst)->nodes++;                                                    \
-} while (/* CONSTCOND */0)
-
-#define DLIST_SWAP(dst, src, nod, ins) do {                            \
-    register node_t *prev = (nod)->prev, *next = (nod)->next;          \
-                                                                       \
-    if (prev != NULL)                                                  \
-       prev->next = next;                                              \
-    else                                                               \
-       (src)->top = next;                                              \
-    if (next != NULL)                                                  \
-       next->prev = prev;                                              \
-    else                                                               \
-       (src)->bottom = prev;                                           \
-    (src)->nodes--;                                                    \
-    if ((ins)) {                                                       \
-       if ((prev = (dst)->top) != NULL) {                              \
-           prev->prev = (nod);                                         \
-           (nod)->prev = NULL;                                         \
-           (nod)->next = prev;                                         \
-           (dst)->top = (nod);                                         \
-       } else {                                                        \
-           (dst)->top = (dst)->bottom = (nod);                         \
-           (nod)->next = (nod)->prev = NULL;                           \
-       }                                                               \
-    } else {                                                           \
-       if ((prev = (dst)->bottom) != NULL) {                           \
-           prev->next = (nod);                                         \
-           (nod)->prev = prev;                                         \
-           (nod)->next = NULL;                                         \
-           (dst)->bottom = (nod);                                      \
-       } else {                                                        \
-           (dst)->bottom = (dst)->top = (nod);                         \
-           (nod)->next = (nod)->prev = NULL;                           \
-       }                                                               \
-    }                                                                  \
-    (dst)->nodes++;                                                    \
-} while (/* CONSTCOND */0)
-
-#define DLIST_TOP(lst)         ((void *)((list_t *)(lst))->top)
-#define DLIST_BOTTOM(lst)      ((void *)((list_t *)(lst))->bottom)
-#define DLIST_NEXT(var)                ((void *)((node_t *)(var))->next)
-#define DLIST_PREV(var)                ((void *)((node_t *)(var))->prev)
-
-#define DLIST_FOREACH(lst, var)                                                \
-    for ((var) = DLIST_TOP((lst)); (var) != NULL; (var) = DLIST_NEXT((var)))
-
-#define DLIST_NODES(lst)       (((list_t *)(lst))->nodes)
-
-
-
-#endif
diff --git a/Xisop/src/common/kernlib/make.sh b/Xisop/src/common/kernlib/make.sh
deleted file mode 100755 (executable)
index 0bf7318..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-# $Id: make.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ../../makedefs.sh
-
-buildlib string
-show $C_AR ar/string.a string/*.o
-show $C_RANLIB ar/string.a
-
-buildlib .
-show $C_AR ar/kernlib.a *.o
-show $C_RANLIB ar/kernlib.a
diff --git a/Xisop/src/common/kernlib/rand.c b/Xisop/src/common/kernlib/rand.c
deleted file mode 100644 (file)
index f2071fe..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/* $Id: rand.c,v 1.2 2004/01/29 04:56:50 mmondor Exp $ */
-
-/*
- * Copyright (C) 2001-2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* Algorithm was borrowed from:
- *      Compute x[n + 1] = (7^5 * x[n]) mod (2^31 - 1).
- * "Random number generators: good ones are hard to find",
- * Park and Miller, Communications of the ACM, vol. 31, no. 10,
- * October 1988, p. 1195.
- *
- * The 10,000nth invokation with default initial seed of 1 should result
- * in 1043618065. Of course, this is a highly predictable algorithm, but
- * it is rather well distributed, while also being quite fast, and is thus
- * suitable in the implementation of ANSI/C89 rand(3)/srand(3) functions.
- * Do NOT use for cryptography related work.
- *  Matt
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/rand.h>
-
-
-
-static unsigned int global_seed = 1;
-
-
-
-int rand(void)
-{
-    /*
-    register int a, b;
-
-    a = b = (signed int)global_seed;
-    a /= 127773;
-    b %= 127773;
-
-    b *= 16807;
-    a *= 2836;
-    b -= a;
-    if (b <= 0)
-       b += 0x7fffffff;
-
-    global_seed = b;
-
-    return b;
-    */
-
-    int v;
-
-    if ((v = (global_seed % 127773 * 16807) -
-               (global_seed / 127773 * 2836)) < 1)
-       v += 0x7fffffff;
-    global_seed = v;
-
-    return v;
-}
-
-
-void srand(unsigned int seed)
-{
-    global_seed = seed;
-}
-
-
-/* This is the POSIX reentrant variant where caller supplies seed */
-int rand_r(unsigned int *seed)
-{
-    int v;
-
-    if ((v = (*seed % 127773 * 16807) - (*seed / 127773 * 2836)) < 1)
-       v += 0x7fffffff;
-    *seed = v;
-
-    return v;
-}
diff --git a/Xisop/src/common/kernlib/rand.h b/Xisop/src/common/kernlib/rand.h
deleted file mode 100644 (file)
index 29ed498..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* $Id: rand.h,v 1.1 2004/01/29 04:55:06 mmondor Exp $ */
-
-/*
- * Copyright (C) 2001-2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNLIB_RAND_H
-#define KERNLIB_RAND_H
-
-
-
-#include <common/types.h>
-
-
-
-int rand(void);
-void srand(unsigned int);
-int rand_r(unsigned int *);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernlib/setjmp.h b/Xisop/src/common/kernlib/setjmp.h
deleted file mode 100644 (file)
index e19e520..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* $Id: setjmp.h,v 1.1 2004/01/30 07:01:24 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNLIB_SETJMP_H
-#define KERNLIB_SETJMP_H
-
-
-
-/* These functions, as well as _ctx_t are defined by the processor-specific
- * support headerfile, <processor/support.h>. These are the C89/ANSI
- * setjmp()/longjmp().
- */
-
-
-
-#include <common/types.h>
-#include <processor/support.h>
-
-
-
-typedef _ctx_t jmp_buf[1];
-
-
-
-int setjmp(jmp_buf);
-void longjmp(jmp_buf, int);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernlib/string.h b/Xisop/src/common/kernlib/string.h
deleted file mode 100644 (file)
index cba5365..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/* $Id: string.h,v 1.3 2004/06/03 05:40:46 mmondor Exp $ */
-
-/*
- * Copyright (C) 1989-2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef KERNLIB_STRING_H
-#define KERNLIB_STRING_H
-
-
-
-#include <common/types.h>
-#include <processor/support.h>
-
-
-
-/* This is used for some kernel strings, such as public message port names */
-typedef struct bstr {
-    size_t size, len;  /* Maximum and current lengths */
-    u_int8_t data[1];  /* Actual buffer follows */
-} bstr_t;
-
-
-bstr_t *bstr_alloc(size_t);
-bstr_t *bstr_new(const char *, size_t, bool);
-bstr_t *bstr_free(bstr_t *);
-
-
-
-/* More conventional string functions */
-size_t strlen(const char *);
-size_t strnlen(const char *, size_t);
-
-char *_strcpy(char *, const char *);
-size_t _strncpy(char *, const char *, size_t);
-
-char *_strcat(char *, const char *);
-char *_strncat(char *, const char *, size_t);
-
-int strcmp(const char *, const char *);
-int strncmp(const char *, const char *, size_t);
-
-char *strchr(const char *, int);
-char *strnchr(const char *, int, size_t);
-char *strrchr(const char *, int);
-char *strnrchr(const char *, int, size_t);
-
-char *_strdup(const char *);
-char *_strndup(const char *, size_t);
-
-int straspl(char **, char *, int);
-int strspl(char **, char *, int, char);
-
-int strcasecmp(const char *, const char *);
-int strncasecmp(const char *, const char *, size_t);
-void _strlower(char *);
-void _strupper(char *);
-u_int32_t _strpack32(const char *, size_t);
-u_int32_t _memcasehash32(const void *, size_t);
-int _memcasecmp(const void *, const void *, size_t);
-
-u_int32_t htol(const char *);
-void _strrev(char *);
-u_int32_t memhash32(const void *, size_t);
-
-#define memclr(a, l)   memset((a), 0, (l))
-int memcmp(const void *, const void *, size_t);
-void *memcpy(void *, const void *, size_t);
-void *memmove(void *, const void *, size_t);
-void *memset(void *, int, size_t);
-void pageclr(void *, u_int32_t);
-
-
-
-#endif
diff --git a/Xisop/src/common/kernlib/string/_strcat.c b/Xisop/src/common/kernlib/string/_strcat.c
deleted file mode 100644 (file)
index f431a05..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* $Id: _strcat.c,v 1.1 2004/06/03 05:40:02 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-/* XXX Unlike ANSI, returns pointer at end of destination rather to beginning
- * to allow special optimizations in loops.
- */
-char *_strcat(char *dest, const char *src)
-{
-    for (; *dest != '\0'; dest++) ;
-    for (; (*dest = *src++) != '\0'; dest++) ;
-
-    return (dest);
-}
diff --git a/Xisop/src/common/kernlib/string/_strcpy.c b/Xisop/src/common/kernlib/string/_strcpy.c
deleted file mode 100644 (file)
index affc726..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* $Id: _strcpy.c,v 1.1 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-/* XXX Unlike standard strcpy(), returns pointer to end of copied string in
- * destination, rather than to beginning, more useful to optimize some loops.
- * This variant should never be called strcpy() (i.e., could be called
- * _strcpy() however).
- */
-char *_strcpy(char *dest, const char *src)
-{
-    for (; (*dest = *src++) != '\0'; dest++) ;
-
-    return (dest);
-}
diff --git a/Xisop/src/common/kernlib/string/_strdup.c b/Xisop/src/common/kernlib/string/_strdup.c
deleted file mode 100644 (file)
index 76a78c9..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* $Id: _strdup.c,v 1.3 2004/06/03 05:54:44 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/main.h>
-#include <common/kernlib/string.h>
-
-
-
-/* Uses kernel memory pool, should only be used by kernel code */
-char *_strdup(const char *str)
-{
-    char *new;
-    register const char *ptr;
-    register size_t len;
-
-    for (new = NULL, ptr = str; *ptr != '\0'; ptr++) ;
-
-    len = (size_t)(ptr - str) + 1;
-    if ((new = MALLOC(len)) != NULL)
-       (void) memcpy(new, str, len);
-
-    return new;
-}
diff --git a/Xisop/src/common/kernlib/string/_strncat.c b/Xisop/src/common/kernlib/string/_strncat.c
deleted file mode 100644 (file)
index 61115b2..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* $Id: _strncat.c,v 1.1 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-/* XXX Unlike ANSI, returns pointer at end of destination rather to beginning
- * to allow special optimizations in loops.
- */
-char *_strncat(char *dest, const char *src, size_t max)
-{
-    if (max != 0) {
-       register const char *toptr;
-
-       for (toptr = dest, toptr += max; dest < toptr && *dest != '\0';
-               dest++) ;
-       for (; dest < toptr && (*dest = *src++) != '\0'; dest++) ;
-       if (dest < toptr)
-           *dest = '\0';
-    }
-
-    return dest;
-}
diff --git a/Xisop/src/common/kernlib/string/_strncpy.c b/Xisop/src/common/kernlib/string/_strncpy.c
deleted file mode 100644 (file)
index d9132eb..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* $Id: _strncpy.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-/* Unlike the useless return code of the standard ANSI one,
- * this function returns the number of bytes successfully copied.
- */
-size_t _strncpy(char *dest, const char *src, size_t max)
-{
-    if (max > 0) {
-       register const char *sptr;
-       register char *toptr;
-
-       for (sptr = src, toptr = dest, toptr += max;
-               dest < toptr && (*dest = *sptr) != '\0'; sptr++, dest++) ;
-       if (dest == toptr)
-           *dest = '\0';
-
-       return ((size_t)(sptr - src));
-    }
-
-    *dest = '\0';
-    return 0;
-}
diff --git a/Xisop/src/common/kernlib/string/_strndup.c b/Xisop/src/common/kernlib/string/_strndup.c
deleted file mode 100644 (file)
index 007d15e..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* $Id: _strndup.c,v 1.3 2004/06/03 05:54:44 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/main.h>
-#include <common/kernlib/string.h>
-
-
-
-/* Uses kernel memory. */
-char *_strndup(const char *str, size_t max)
-{
-    char *new;
-    register const char *ptr, *toptr;
-    size_t len;
-
-    for (toptr = ptr = str, toptr += max, new = NULL;
-           ptr < toptr && *ptr != '\0'; ptr++) ;
-    len = (size_t)(ptr - str);
-    if ((new = MALLOC(len + 1)) != NULL) {
-       (void) memcpy(new, str, len);
-       new[len] = '\0';
-    }
-
-    return new;
-}
diff --git a/Xisop/src/common/kernlib/string/_strrev.c b/Xisop/src/common/kernlib/string/_strrev.c
deleted file mode 100644 (file)
index 3019ad2..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* $Id: _strrev.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-/* Iteratively reverses the supplied string */
-void _strrev(char *str)
-{
-    register char *p1, *p2, t;
-
-    for (p1 = p2 = str; *p2; p2++) ;
-    if (p2 > p1)
-       p2--;
-
-    for (;p1 < p2; p1++, p2--) {
-       t = *p1;
-       *p1 = *p2;
-       *p2 = t;
-    }
-}
diff --git a/Xisop/src/common/kernlib/string/bstr_alloc.c b/Xisop/src/common/kernlib/string/bstr_alloc.c
deleted file mode 100644 (file)
index 34b63c6..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* $Id: bstr_alloc.c,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/main.h>
-
-
-
-/* This is always allocated using kernel memory, and is for use by kernel
- * functions.
- */
-bstr_t *bstr_alloc(size_t size)
-{
-    bstr_t *bstr = NULL;
-
-    if ((bstr = MALLOC(sizeof(bstr_t) + size + 1)) != NULL) {
-       bstr->size = size;
-       bstr->len = 0;
-       *bstr->data = 0;
-    }
-
-    return bstr;
-}
diff --git a/Xisop/src/common/kernlib/string/bstr_free.c b/Xisop/src/common/kernlib/string/bstr_free.c
deleted file mode 100644 (file)
index ba7b837..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* $Id: bstr_free.c,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-#include <common/kernel/memory.h>
-
-
-
-bstr_t *bstr_free(bstr_t *bstr)
-{
-    if (bstr != NULL)
-       FREE(bstr);
-
-    return NULL;
-}
diff --git a/Xisop/src/common/kernlib/string/bstr_new.c b/Xisop/src/common/kernlib/string/bstr_new.c
deleted file mode 100644 (file)
index 04eca59..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/* $Id: bstr_new.c,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/main.h>
-
-
-
-/* This is always allocated using kernel memory, and is for use by kernel
- * functions.
- */
-bstr_t *bstr_new(const char *string, size_t max, bool fixed)
-{
-    register bstr_t *bstr = NULL;
-    register size_t len = strnlen(string, max);
-    register size_t size;
-
-    if (fixed)
-       size = max;
-    else
-       size = len;
-
-    if ((bstr = MALLOC(sizeof(bstr_t) + size + 1)) != NULL) {
-       bstr->size = size;
-       bstr->len = len;
-       memcpy(bstr->data, string, len);
-       bstr->data[len] = 0;
-    }
-
-    return bstr;
-}
diff --git a/Xisop/src/common/kernlib/string/case.c b/Xisop/src/common/kernlib/string/case.c
deleted file mode 100644 (file)
index 4835110..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/* $Id: case.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-static const unsigned char toupper_table[] = {
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 
-    0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 
-    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 
-    0x1E, 0x1F, ' ',  '!',  '"',  '#',  '$',  '%',  '&',  0x27, 
-    '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',  '0',  '1',  
-    '2',  '3',  '4',  '5',  '6',  '7',  '8',  '9',  ':',  ';',  
-    '<',  '=',  '>',  '?',  '@',  'A',  'B',  'C',  'D',  'E',  
-    'F',  'G',  'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',  
-    'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',  'X',  'Y',  
-    'Z',  '[',  0x5C, ']',  '^',  '_',  '`',  'A',  'B',  'C',  
-    'D',  'E',  'F',  'G',  'H',  'I',  'J',  'K',  'L',  'M',  
-    'N',  'O',  'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',  
-    'X',  'Y',  'Z',  '{',  '|',  '}',  '~',  0x7F, 0x80, 0x81, 
-    0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 
-    0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 
-    0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 
-    0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 
-    0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 
-    0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 
-    0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 
-    0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 
-    0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 
-    0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 
-    0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 
-    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 
-    0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
-};
-
-static const unsigned char tolower_table[] = {
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 
-    0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 
-    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 
-    0x1E, 0x1F, ' ',  '!',  '"',  '#',  '$',  '%',  '&',  0x27, 
-    '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',  '0',  '1',  
-    '2',  '3',  '4',  '5',  '6',  '7',  '8',  '9',  ':',  ';',  
-    '<',  '=',  '>',  '?',  '@',  'a',  'b',  'c',  'd',  'e',  
-    'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',  
-    'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',  'y',  
-    'z',  '[',  0x5C, ']',  '^',  '_',  '`',  'a',  'b',  'c',  
-    'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',  
-    'n',  'o',  'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  
-    'x',  'y',  'z',  '{',  '|',  '}',  '~',  0x7F, 0x80, 0x81, 
-    0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 
-    0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 
-    0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 
-    0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 
-    0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 
-    0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 
-    0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 
-    0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 
-    0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 
-    0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 
-    0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 
-    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 
-    0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
-};
-
-
-
-int strcasecmp(const char *s1, const char *s2)
-{
-    register const unsigned char *us1, *us2;
-    register unsigned char cs1, cs2;
-
-    for (us1 = (const unsigned char *)s1, us2 = (const unsigned char *)s2,
-           cs1 = tolower_table[(int)*us1], cs2 = tolower_table[(int)*us2];
-           cs1 != '\0' && cs2 != '\0' &&
-           (cs1 = tolower_table[(int)*us1]) ==
-           (cs2 = tolower_table[(int)*us2]);
-           us1++, us2++) ;
-
-    return ((int)(cs1 - cs2));
-}
-
-
-int strncasecmp(const char *s1, const char *s2, size_t max)
-{
-    register const unsigned char *us1, *us2, *toptr;
-    register unsigned char cs1, cs2;
-
-    if (max == 0)
-       return 0;
-
-    for (us1 = (const unsigned char *)s1, us2 = (const unsigned char *)s2,
-           cs1 = tolower_table[(int)*us1], cs2 = tolower_table[(int)*us2],
-           toptr = us1, toptr += max;
-           us1 < toptr && cs1 != '\0' && cs2 != '\0' &&
-           (cs1 = tolower_table[(int)*us1]) ==
-           (cs2 = tolower_table[(int)*us2]);
-           us1++, us2++) ;
-
-    return (us1 < toptr ? ((int)(cs1 - cs2)) : 0);
-}
-
-
-void _strlower(char *str)
-{
-    register unsigned char *ustr;
-
-    for (ustr = (unsigned char *)str; *ustr != '\0'; ustr++)
-       *ustr = tolower_table[(int)*ustr];
-}
-
-
-void _strupper(char *str)
-{
-    register unsigned char *ustr;
-
-    for (ustr = (unsigned char *)str; *ustr != '\0'; ustr++)
-       *ustr = toupper_table[(int)*ustr];
-}
-
-
-/* This function generates a 32-bit hash using the supplied string which
- * is suitable for fast lookup for command comparision. It simply converts
- * characters to uppercase and stores them in the value. It of course can
- * only perform this for 4 bytes. It will stop at either end of string '\0'
- * or space ' '. If the string has more than 4 characters -1 is returned.
- */
-u_int32_t _strpack32(const char *str, size_t min)
-{
-    register unsigned const char *ustr;
-    register u_int32_t hash = 0;
-    size_t i;
-
-    for (ustr = (unsigned const char *)str, i = 0; *ustr > 32 && i < 5; i++) {
-       hash <<= 8;
-       hash |= toupper_table[(int)*ustr++];
-    }
-    if (i < min || i > 4)
-       hash = 0;
-
-    return hash;
-}
-
-
-/* These functions are useful to use in conjunction with hash tables if
- * case-insensitive processing of data is required while case-sensitivity of
- * records storage must be preserved.
- */
-
-u_int32_t _memcasehash32(const void *mem, size_t size)
-{
-    register u_int32_t hash;
-    register const unsigned char *curmem, *tomem;
-
-    hash = 0;
-    curmem = tomem = mem;
-    tomem += size;
-
-#if !defined(_ARCH_LOWCACHE)
-    while (curmem < tomem - 4) {
-#if !defined(_ARCH_USEINDEXING)
-       hash = toupper_table[(int)*curmem++] + (31 * hash);
-       hash = toupper_table[(int)*curmem++] + (31 * hash);
-       hash = toupper_table[(int)*curmem++] + (31 * hash);
-       hash = toupper_table[(int)*curmem++] + (31 * hash);
-#else  /* !defined(_ARCH_USEINDEXING) */
-       hash = toupper_table[(int)curmem[0]] + (31 * hash);
-       hash = toupper_table[(int)curmem[1]] + (31 * hash);
-       hash = toupper_table[(int)curmem[2]] + (31 * hash);
-       hash = toupper_table[(int)curmem[3]] + (31 * hash);
-       curmem += 4;
-#endif /* !defined(_ARCH_USEINDEXING) */
-    }
-#endif /* !defined(_ARCH_LOWCACHE) */
-    while (curmem < tomem)
-       hash = toupper_table[(int)*curmem++] + (31 * hash);
-
-    return hash;
-}
-
-int _memcasecmp(const void *s1, const void *s2, size_t size)
-{
-    register const unsigned char *ptr1, *ptr2, *toptr;
-
-#define CMP()  toupper_table[(int)*ptr1++] != toupper_table[(int)*ptr2++]
-#define RET()  return (int)(toupper_table[(int)*(--ptr1)] - \
-                       toupper_table[(int)*(--ptr2)])
-
-    ptr1 = toptr = s1;
-    toptr += size;
-    ptr2 = s2;
-
-#if !defined(_ARCH_LOWCACHE)
-    while (ptr1 < toptr - 4)
-       if (CMP() || CMP() || CMP() || CMP())
-           RET();
-#endif
-    while (ptr1 < toptr)
-       if (CMP())
-           RET();
-
-#undef CMP
-#undef RET
-
-    return 0;
-}
diff --git a/Xisop/src/common/kernlib/string/htol.c b/Xisop/src/common/kernlib/string/htol.c
deleted file mode 100644 (file)
index 79ef88d..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/* $Id: htol.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-/* Converts an hexadecimal string to u_int32_t */
-u_int32_t htol(const char *s)
-{
-    register u_int32_t v = 0;
-
-    while (*s) {
-       if (*s >= '0' && *s <= '9') {
-           if (v <= (u_int16_t)-1)
-               v = (u_int16_t)v * 16;
-           else
-               v = v * 16;
-           v += *s++ - '0';
-       } else if (*s >= 'a' && *s <= 'f') {
-           if (v <= (u_int16_t)-1)
-               v = (u_int16_t)v * 16;
-           else
-               v = v * 16;
-           v += *s++ - 87;
-       } else if (*s >= 'A' && *s <= 'F') {
-           if (v <= (u_int16_t)-1)
-               v = (u_int16_t)v * 16;
-           else
-               v = v * 16;
-           v += *s++ - 55;
-       } else break;
-    }
-
-    return v;
-}
diff --git a/Xisop/src/common/kernlib/string/memcmp.c b/Xisop/src/common/kernlib/string/memcmp.c
deleted file mode 100644 (file)
index 6b3b0f9..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/* $Id: memcmp.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-int memcmp(const void *dest, const void *src, size_t len)
-{
-    register const unsigned char *ptr, *toptr, *dptr;
-
-    ptr = toptr = src;
-    toptr += len;
-    dptr = dest;
-
-#define RET(a, b)      return (int)(*(--(a)) - *(--(b)))
-
-#if _ARCH_INT_BITS == 8
-
-#if !defined(_ARCH_LOWCACHE)
-    while (ptr < toptr - 8)
-       if (*ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ ||
-           *ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ ||
-           *ptr++ != *dptr++ || *ptr++ != *dptr++)
-           RET(dptr, ptr);
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-    while (ptr < toptr)
-       if (*ptr++ != *dptr++)
-           RET(dptr, ptr);
-
-#else                          /* _ARCH_INT_BITS != 8 */
-
-    if (len < 32 || ((int)ptr % sizeof(int)) != ((int)dptr % sizeof(int))) {
-#if !defined(_ARCH_LOWCACHE)
-       while (ptr < toptr - 8)
-           if (*ptr++ != *dptr++ || *ptr++ != *dptr++ || *ptr++ != *dptr++ ||
-                   *ptr++ != *dptr++ || *ptr++ != *dptr++ ||
-                   *ptr++ != *dptr++ || *ptr++ != *dptr++ ||
-                   *ptr++ != *dptr++)
-               RET(dptr, ptr);
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-       while (ptr < toptr)
-           if (*ptr++ != *dptr++)
-               RET(dptr, ptr);
-    } else {
-       register const unsigned int *lptr, *ltoptr, *ldptr, *ldtoptr;
-       register const unsigned char *dtoptr;
-
-       dtoptr = dptr;
-       dtoptr += len;
-       lptr = (const unsigned int *)OALIGN_CEIL(ptr, int);
-       ltoptr = (const unsigned int *)OALIGN_FLOOR(toptr, int);
-       ldptr = (const unsigned int *)OALIGN_CEIL(dptr, int);
-       ldtoptr = (const unsigned int *)OALIGN_FLOOR(dtoptr, int);
-       if (ldtoptr - ldptr < ltoptr - lptr)
-           ltoptr--;
-
-       while (ptr < (const unsigned char *)lptr)
-           if (*ptr++ != *dptr++)
-               RET(dptr, ptr);
-#if !defined(_ARCH_LOWCACHE)
-       while (lptr < ltoptr - (sizeof(int) * 8)) {
-           if (*lptr++ != *ldptr++ || *lptr++ != *ldptr++ ||
-                   *lptr++ != *ldptr++ || *lptr++ != *ldptr++ ||
-                   *lptr++ != *ldptr++ || *lptr++ != *ldptr++ ||
-                   *lptr++ != *ldptr++ || *lptr++ != *ldptr++)
-               RET(ldptr, lptr);
-       }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-       while (lptr < ltoptr)
-           if (*lptr++ != *ldptr++)
-               RET(ldptr, lptr);
-       ptr = (const unsigned char *)lptr;
-       dptr = (const unsigned char *)ldptr;
-       while (ptr < toptr)
-           if (*ptr++ != *dptr++)
-               RET(dptr, ptr);
-    }
-
-#endif                         /* _ARCH_INT_BITS == 8 */
-
-#undef RET
-
-    return 0;
-}
diff --git a/Xisop/src/common/kernlib/string/memcpy.c b/Xisop/src/common/kernlib/string/memcpy.c
deleted file mode 100644 (file)
index 398d91e..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/* $Id: memcpy.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-void *memcpy(void *dest, const void *src, size_t len)
-{
-    register const unsigned char *ptr, *toptr;
-    register unsigned char *dptr;
-
-    ptr = toptr = src;
-    toptr += len;
-    dptr = dest;
-
-#if _ARCH_INT_BITS == 8
-
-#if !defined(_ARCH_LOWCACHE)
-    while (ptr < toptr - 8) {
-#if !defined(_ARCH_USEINDEXING)
-       *dptr++ = *ptr++;
-       *dptr++ = *ptr++;
-       *dptr++ = *ptr++;
-       *dptr++ = *ptr++;
-       *dptr++ = *ptr++;
-       *dptr++ = *ptr++;
-       *dptr++ = *ptr++;
-       *dptr++ = *ptr++;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-       dptr[0] = ptr[0];
-       dptr[1] = ptr[1];
-       dptr[2] = ptr[2];
-       dptr[3] = ptr[3];
-       dptr[4] = ptr[4];
-       dptr[5] = ptr[5];
-       dptr[6] = ptr[6];
-       dptr[7] = ptr[7];
-       dptr += 8;
-       ptr += 8;
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-    }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-    while (ptr < toptr)
-       *dptr++ = *ptr++;
-
-#else                          /* _ARCH_INT_BITS != 8 */
-
-    if (len < 32 || ((int)ptr % sizeof(int)) != ((int)dptr % sizeof(int))) {
-#if !defined(_ARCH_LOWCACHE)
-       while (ptr < toptr - 8) {
-#if !defined(_ARCH_USEINDEXING)
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-           dptr[0] = ptr[0];
-           dptr[1] = ptr[1];
-           dptr[2] = ptr[2];
-           dptr[3] = ptr[3];
-           dptr[4] = ptr[4];
-           dptr[5] = ptr[5];
-           dptr[6] = ptr[6];
-           dptr[7] = ptr[7];
-           dptr += 8;
-           ptr += 8;
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-       }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-       while (ptr < toptr)
-           *dptr++ = *ptr++;
-    } else {
-       register const unsigned int *lptr, *ltoptr;
-       register unsigned int *ldptr, *ldtoptr;
-       register unsigned char *dtoptr;
-
-       dtoptr = dptr;
-       dtoptr += len;
-       lptr = (const unsigned int *)OALIGN_CEIL(ptr, int);
-       ltoptr = (const unsigned int *)OALIGN_FLOOR(toptr, int);
-       ldptr = (unsigned int *)OALIGN_CEIL(dptr, int);
-       ldtoptr = (unsigned int *)OALIGN_FLOOR(dtoptr, int);
-       if (ldtoptr - ldptr < ltoptr - lptr)
-           ltoptr--;
-
-       while (ptr < (const unsigned char *)lptr)
-           *dptr++ = *ptr++;
-#if !defined(_ARCH_LOWCACHE)
-       while (lptr < ltoptr - (sizeof(int) * 8)) {
-#if !defined(_ARCH_USEINDEXING)
-           *ldptr++ = *lptr++;
-           *ldptr++ = *lptr++;
-           *ldptr++ = *lptr++;
-           *ldptr++ = *lptr++;
-           *ldptr++ = *lptr++;
-           *ldptr++ = *lptr++;
-           *ldptr++ = *lptr++;
-           *ldptr++ = *lptr++;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-           ldptr[0] = lptr[0];
-           ldptr[1] = lptr[1];
-           ldptr[2] = lptr[2];
-           ldptr[3] = lptr[3];
-           ldptr[4] = lptr[4];
-           ldptr[5] = lptr[5];
-           ldptr[6] = lptr[6];
-           ldptr[7] = lptr[7];
-           ldptr = &ldptr[8];
-           lptr = &lptr[8];
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-       }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-       while (lptr < ltoptr)
-           *ldptr++ = *lptr++;
-       ptr = (unsigned const char *)lptr;
-       dptr = (unsigned char *)ldptr;
-       while (ptr < toptr)
-           *dptr++ = *ptr++;
-    }
-
-#endif                         /* _ARCH_INT_BITS == 8 */
-
-    return dest;
-}
diff --git a/Xisop/src/common/kernlib/string/memhash32.c b/Xisop/src/common/kernlib/string/memhash32.c
deleted file mode 100644 (file)
index 9184827..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* $Id: memhash32.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-u_int32_t memhash32(const void *mem, size_t size)
-{
-    register u_int32_t hash;
-    register const unsigned char *curmem, *tomem;
-
-    hash = 0;
-    curmem = tomem = mem;
-    tomem += size;
-
-#if !defined(_ARCH_LOWCACHE)
-    while (curmem < tomem - 4) {
-#if !defined(_ARCH_USEINDEXING)
-       hash = *curmem++ + (31 * hash);
-       hash = *curmem++ + (31 * hash);
-       hash = *curmem++ + (31 * hash);
-       hash = *curmem++ + (31 * hash);
-#else  /* !defined(_ARCH_USEINDEXING) */
-       hash = curmem[0] + (31 * hash);
-       hash = curmem[1] + (31 * hash);
-       hash = curmem[2] + (31 * hash);
-       hash = curmem[3] + (31 * hash);
-       curmem += 4;
-#endif /* !defined(_ARCH_USEINDEXING) */
-    }
-#endif /* !defined(_ARCH_LOWCACHE) */
-    while (curmem < tomem)
-       hash = *curmem++ + (31 * hash);
-
-    return hash;
-}
diff --git a/Xisop/src/common/kernlib/string/memmove.c b/Xisop/src/common/kernlib/string/memmove.c
deleted file mode 100644 (file)
index cd0db28..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/* $Id: memmove.c,v 1.1 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-/* Can work with overlapping areas */
-void *memmove(void *dest, const void *src, size_t len)
-{
-    register const unsigned char *ptr = NULL, *toptr = NULL;
-    register unsigned char *dptr = NULL;
-    size_t d;
-
-    if (dest < src)
-       d = (const unsigned char *)src - (unsigned char *)dest;
-    else
-       d = (unsigned char *)dest - (const unsigned char *)src;
-
-#if _ARCH_INT_BITS == 8
-
-    if (dest < src) {
-       /* Copy in increasing order */
-       ptr = toptr = (const unsigned char *)src;
-       toptr += len;
-       dptr = dest;
-#if !defined(_ARCH_LOWCACHE)
-       while (ptr < toptr - 8) {
-#if !defined(_ARCH_USEINDEXING)
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-           *dptr++ = *ptr++;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-           dptr[0] = ptr[0];
-           dptr[1] = ptr[1];
-           dptr[2] = ptr[2];
-           dptr[3] = ptr[3];
-           dptr[4] = ptr[4];
-           dptr[5] = ptr[5];
-           dptr[6] = ptr[6];
-           dptr[7] = ptr[7];
-           dptr += 8;
-           ptr += 8;
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-       }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-       while (ptr < toptr)
-           *dptr++ = *ptr++;
-    } else if (dest > src) {
-       /* Copy in reverse order */
-       ptr = toptr = (const unsigned char *)src;
-       ptr += len;
-       dptr = dest;
-       dptr += len;
-#if !defined(_ARCH_LOWCACHE)
-       while (ptr >= toptr + 8) {
-#if !defined(_ARCH_USEINDEXING)
-           *dptr-- = *ptr--;
-           *dptr-- = *ptr--;
-           *dptr-- = *ptr--;
-           *dptr-- = *ptr--;
-           *dptr-- = *ptr--;
-           *dptr-- = *ptr--;
-           *dptr-- = *ptr--;
-           *dptr-- = *ptr--;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-           dptr[0] = ptr[0];
-           dptr[-1] = ptr[-1];
-           dptr[-2] = ptr[-2];
-           dptr[-3] = ptr[-3];
-           dptr[-4] = ptr[-4];
-           dptr[-5] = ptr[-5];
-           dptr[-6] = ptr[-6];
-           dptr[-7] = ptr[-7];
-           dptr -= 8;
-           ptr -= 8;
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-       }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-       while (ptr >= toptr)
-           *dptr-- = *ptr--;
-    }
-
-#else                          /* _ARCH_INT_BITS != 8 */
-
-    if (len < 32 || d < sizeof(int) ||
-       ((int)ptr % sizeof(int)) != ((int)dptr % sizeof(int))) {
-       if (dest < src) {
-           /* Copy in increasing order */
-           ptr = toptr = (const unsigned char *)src;
-           toptr += len;
-           dptr = dest;
-#if !defined(_ARCH_LOWCACHE)
-           while (ptr < toptr - 8) {
-#if !defined(_ARCH_USEINDEXING)
-               *dptr++ = *ptr++;
-               *dptr++ = *ptr++;
-               *dptr++ = *ptr++;
-               *dptr++ = *ptr++;
-               *dptr++ = *ptr++;
-               *dptr++ = *ptr++;
-               *dptr++ = *ptr++;
-               *dptr++ = *ptr++;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-               dptr[0] = ptr[0];
-               dptr[1] = ptr[1];
-               dptr[2] = ptr[2];
-               dptr[3] = ptr[3];
-               dptr[4] = ptr[4];
-               dptr[5] = ptr[5];
-               dptr[6] = ptr[6];
-               dptr[7] = ptr[7];
-               dptr += 8;
-               ptr += 8;
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-           }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-           while (ptr < toptr)
-               *dptr++ = *ptr++;
-       } else if (dest > src) {
-           /* Copy in reverse order */
-           ptr = toptr = (const unsigned char *)src;
-           ptr += len;
-           dptr = dest;
-           dptr += len;
-#if !defined(_ARCH_LOWCACHE)
-           while (ptr >= toptr + 8) {
-#if !defined(_ARCH_USEINDEXING)
-               *dptr-- = *ptr--;
-               *dptr-- = *ptr--;
-               *dptr-- = *ptr--;
-               *dptr-- = *ptr--;
-               *dptr-- = *ptr--;
-               *dptr-- = *ptr--;
-               *dptr-- = *ptr--;
-               *dptr-- = *ptr--;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-               dptr[0] = ptr[0];
-               dptr[-1] = ptr[-1];
-               dptr[-2] = ptr[-2];
-               dptr[-3] = ptr[-3];
-               dptr[-4] = ptr[-4];
-               dptr[-5] = ptr[-5];
-               dptr[-6] = ptr[-6];
-               dptr[-7] = ptr[-7];
-               dptr -= 8;
-               ptr -= 8;
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-           }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-           while (ptr >= toptr)
-               *dptr-- = *ptr--;
-       }
-    } else {
-       if (dest < src) {
-           /* Increasing order */
-           register const unsigned int *lptr, *ltoptr;
-           register unsigned int *ldptr, *ldtoptr;
-           register unsigned char *dtoptr;
-
-           ptr = toptr = (const unsigned char *)src;
-           toptr += len;
-           dptr = dest;
-
-           dtoptr = dptr;
-           dtoptr += len;
-           lptr = (const unsigned int *)OALIGN_CEIL(ptr, int);
-           ltoptr = (const unsigned int *)OALIGN_FLOOR(toptr, int);
-           ldptr = (unsigned int *)OALIGN_CEIL(dptr, int);
-           ldtoptr = (unsigned int *)OALIGN_FLOOR(dtoptr, int);
-           if (ldtoptr - ldptr < ltoptr - lptr)
-               ltoptr--;
-
-           while (ptr < (const unsigned char *)lptr)
-               *dptr++ = *ptr++;
-#if !defined(_ARCH_LOWCACHE)
-           while (lptr < ltoptr - (sizeof(int) * 8)) {
-#if !defined(_ARCH_USEINDEXING)
-               *ldptr++ = *lptr++;
-               *ldptr++ = *lptr++;
-               *ldptr++ = *lptr++;
-               *ldptr++ = *lptr++;
-               *ldptr++ = *lptr++;
-               *ldptr++ = *lptr++;
-               *ldptr++ = *lptr++;
-               *ldptr++ = *lptr++;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-               ldptr[0] = lptr[0];
-               ldptr[1] = lptr[1];
-               ldptr[2] = lptr[2];
-               ldptr[3] = lptr[3];
-               ldptr[4] = lptr[4];
-               ldptr[5] = lptr[5];
-               ldptr[6] = lptr[6];
-               ldptr[7] = lptr[7];
-               ldptr = &ldptr[8];
-               lptr = &lptr[8];
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-           }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-           while (lptr < ltoptr)
-               *ldptr++ = *lptr++;
-           ptr = (const unsigned char *)lptr;
-           dptr = (unsigned char *)ldptr;
-           while (ptr < toptr)
-               *dptr++ = *ptr++;
-       } else if (dest > src) {
-           /* Reverse order */
-           register const int *lptr, *ltoptr;
-           register int *ldptr, *ldtoptr;
-           register char *dtoptr;
-
-           ptr = toptr = (const unsigned char *)src;
-           ptr += len;
-           dptr = dest;
-           dptr += len;
-
-           dtoptr = dest;
-           lptr = (const unsigned int *)OALIGN_FLOOR(ptr, int);
-           ldptr = (unsigned int *)OALIGN_FLOOR(dptr, int);
-           ltoptr = (const unsigned int *)OALIGN_CEIL(toptr, int);
-           ldtoptr = (unsigned int *)OALIGN_CEIL(dtoptr, int);
-           if (ldptr - ldtoptr < lptr - ltoptr)
-               ltoptr++;
-
-           while (ptr >= (const unsigned char *)lptr)
-               *dptr-- = *ptr--;
-#if !defined(_ARCH_LOWCACHE)
-           while (lptr >= ltoptr + (sizeof(int) * 8)) {
-#if !defined(_ARCH_USEINDEXING)
-               *ldptr-- = *lptr--;
-               *ldptr-- = *lptr--;
-               *ldptr-- = *lptr--;
-               *ldptr-- = *lptr--;
-               *ldptr-- = *lptr--;
-               *ldptr-- = *lptr--;
-               *ldptr-- = *lptr--;
-               *ldptr-- = *lptr--;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-               ldptr[0] = lptr[0];
-               ldptr[-1] = lptr[-1];
-               ldptr[-2] = lptr[-2];
-               ldptr[-3] = lptr[-3];
-               ldptr[-4] = lptr[-4];
-               ldptr[-5] = lptr[-5];
-               ldptr[-6] = lptr[-6];
-               ldptr[-7] = lptr[-7];
-               ldptr = &ldptr[-8];
-               lptr = &lptr[-8];
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-           }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-           while (lptr >= ltoptr)
-               *ldptr-- = *lptr--;
-           ptr = (const unsigned char *)lptr;
-           dptr = (unsigned char *)ldptr;
-           while (ptr >= toptr)
-               *dptr-- = *ptr--;
-       }
-    }
-
-#endif                         /* _ARCH_INT_BITS == 8 */
-
-    return dest;
-}
diff --git a/Xisop/src/common/kernlib/string/memset.c b/Xisop/src/common/kernlib/string/memset.c
deleted file mode 100644 (file)
index 65f0cdd..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/* $Id: memset.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-void *memset(void *mem, int fill, size_t len)
-{
-    register unsigned char *ptr, *toptr;
-    u_int8_t byte = (u_int8_t)fill;
-
-    ptr = toptr = mem;
-    toptr += len;
-
-#if _ARCH_INT_BITS == 8
-
-#if !defined(_ARCH_LOWCACHE)
-    while (ptr < toptr - 8) {
-#if !defined(_ARCH_USEINDEXING)
-       *ptr++ = byte;
-       *ptr++ = byte;
-       *ptr++ = byte;
-       *ptr++ = byte;
-       *ptr++ = byte;
-       *ptr++ = byte;
-       *ptr++ = byte;
-       *ptr++ = byte;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-       ptr[0] = byte;
-       ptr[1] = byte;
-       ptr[2] = byte;
-       ptr[3] = byte;
-       ptr[4] = byte;
-       ptr[5] = byte;
-       ptr[6] = byte;
-       ptr[7] = byte;
-       ptr += 8;
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-    }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-    while (ptr < toptr)
-       *ptr++ = byte;
-
-#else                          /* _ARCH_INT_BITS != 8 */
-
-    if (len < 32) {
-#if !defined(_ARCH_LOWCACHE)
-       while (ptr < toptr - 8) {
-#if !defined(_ARCH_USEINDEXING)
-           *ptr++ = byte;
-           *ptr++ = byte;
-           *ptr++ = byte;
-           *ptr++ = byte;
-           *ptr++ = byte;
-           *ptr++ = byte;
-           *ptr++ = byte;
-           *ptr++ = byte;
-#else                          /* !defined(_ARCH_USEDARRAYS) */
-           ptr[0] = byte;
-           ptr[1] = byte;
-           ptr[2] = byte;
-           ptr[3] = byte;
-           ptr[4] = byte;
-           ptr[5] = byte;
-           ptr[6] = byte;
-           ptr[7] = byte;
-           ptr += 8;
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-       }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-       while (ptr < toptr)
-           *ptr++ = byte;
-    } else {
-       register unsigned int *lptr, *ltoptr, lword = 0;
-
-       if (byte != 0) {
-#if _ARCH_INT_BITS == 16
-           lword = ((byte << 8) & 0xff00) | (byte & 0x00ff);
-#elif _ARCH_INT_BITS == 32
-           /* Creating a 16-bit word from the 8-bit one, then the 32-bit word
-            * from the 16-bit one require less instructions.
-            */
-           register u_int16_t tmp;
-
-           tmp = ((byte << 8) & 0xff00) | (byte & 0x00ff);
-           lword = ((tmp << 16) & 0xffff0000) | (tmp & 0x0000ffff);
-#elif _ARCH_INT_BITS == 64
-           /* Unlikely, since long is usually 64-bit on 64-bit archs, leaving
-            * 32-bit ints.
-            * Creating a 16-bit word from the 8-bit one, a 32-bit word from
-            * the 16-bit one and a 64-bit word from the 32-bit one require
-            * less instructions.
-            */
-           register u_int32_t tmp2;
-           register u_int16_t tmp;
-
-           tmp = ((byte << 8) & 0xff00) | (byte & 0x00ff);
-           tmp2 = ((tmp << 16) & 0xffff0000) | (tmp & 0x0000ffff);
-           lword = ((tmp2 << 32) & 0xffffffff00000000ULL) |
-               (tmp2 & 0x00000000ffffffffULL);
-#endif
-       }
-
-       lptr = (unsigned int *)OALIGN_CEIL(ptr, int);
-       ltoptr = (unsigned int *)OALIGN_FLOOR(toptr, int);
-
-       while (ptr < (unsigned char *)lptr)
-           *ptr++ = byte;
-#if !defined(_ARCH_LOWCACHE)
-       while (lptr < ltoptr - (sizeof(int) * 8)) {
-#if !defined(_ARCH_USEINDEXING)
-           *lptr++ = lword;
-           *lptr++ = lword;
-           *lptr++ = lword;
-           *lptr++ = lword;
-           *lptr++ = lword;
-           *lptr++ = lword;
-           *lptr++ = lword;
-           *lptr++ = lword;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-           lptr[0] = lword;
-           lptr[1] = lword;
-           lptr[2] = lword;
-           lptr[3] = lword;
-           lptr[4] = lword;
-           lptr[5] = lword;
-           lptr[6] = lword;
-           lptr[7] = lword;
-           lptr = &lptr[8];
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-       }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-       while (lptr < ltoptr)
-           *lptr++ = lword;
-       ptr = (unsigned char *)lptr;
-       while (ptr < toptr)
-           *ptr++ = byte;
-    }
-
-#endif                         /* _ARCH_INT_BITS == 8 */
-
-    return mem;
-}
diff --git a/Xisop/src/common/kernlib/string/pageclr.c b/Xisop/src/common/kernlib/string/pageclr.c
deleted file mode 100644 (file)
index cb74b59..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* $Id: pageclr.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-#include <port/support.h>
-
-
-
-/* Faster than memset(), but assumes that <mem> be aligned and that _PAGE_SIZE
- * is a multiple of sizeof(int).
- */
-void pageclr(void *mem, u_int32_t many)
-{
-    register int *lptr, *ltoptr, lword = 0;
-
-    lptr = (int *)mem;
-    ltoptr = (int *)(((u_int8_t *)mem + (_PAGE_SIZE * many)));
-
-#if !defined(_ARCH_LOWCACHE)
-    while (lptr < ltoptr - (sizeof(int) * 16)) {
-#if !defined(_ARCH_USEINDEXING)
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-       *lptr++ = lword;
-#else                          /* !defined(_ARCH_USEINDEXING) */
-       lptr[0] = lword;
-       lptr[1] = lword;
-       lptr[2] = lword;
-       lptr[3] = lword;
-       lptr[4] = lword;
-       lptr[5] = lword;
-       lptr[6] = lword;
-       lptr[7] = lword;
-       lptr[8] = lword;
-       lptr[9] = lword;
-       lptr[10] = lword;
-       lptr[11] = lword;
-       lptr[12] = lword;
-       lptr[13] = lword;
-       lptr[14] = lword;
-       lptr[15] = lword;
-       lptr = &lptr[16];
-#endif                         /* !defined(_ARCH_USEINDEXING) */
-    }
-#endif                         /* !defined(_ARCH_LOWCACHE) */
-    while (lptr < ltoptr)
-       *lptr++ = lword;
-}
diff --git a/Xisop/src/common/kernlib/string/straspl.c b/Xisop/src/common/kernlib/string/straspl.c
deleted file mode 100644 (file)
index 7f15a91..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* $Id: straspl.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-/* Splits columns of a string delimited by spaces and/or tabs, and fills
- * char **argv with pointers to each column. Returns the number of columns
- * that could be filled in. The supplied string IS modified.
- */
-int straspl(char **argv, char *str, int maxcols)
-{
-    register char *ptr, *ptr2;
-    int col;
-
-    for (ptr = str, col = 0; *ptr != '\0' && col < maxcols; ) {
-       for (; *ptr == ' ' || *ptr == '\t'; ptr++) ;
-       if (*ptr != '\0') {
-           for (ptr2 = ptr; *ptr != '\0' && *ptr != ' ' && *ptr != '\t';
-                   ptr++) ;
-           if (ptr != ptr2) {
-               if (*ptr != '\0')
-                   *ptr++ = '\0';
-               argv[col++] = ptr2;
-           } else
-               break;
-       } else
-           break;
-    }
-
-    return col;
-}
diff --git a/Xisop/src/common/kernlib/string/strchr.c b/Xisop/src/common/kernlib/string/strchr.c
deleted file mode 100644 (file)
index fd4c51d..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* $Id: strchr.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-char *strchr(const char *str, int c)
-{
-    for (; *str != '\0' && *str != c; str++) ;
-
-    return (*str != '\0' ? (char *)str : NULL);
-}
diff --git a/Xisop/src/common/kernlib/string/strcmp.c b/Xisop/src/common/kernlib/string/strcmp.c
deleted file mode 100644 (file)
index 3d5c931..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* $Id: strcmp.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-int strcmp(const char *s1, const char *s2)
-{
-    for (; *s1 != '\0' && *s2 != '\0' && *s1 == *s2; s1++, s2++) ;
-
-    return ((int)((const unsigned char)*s1 - (const unsigned char)*s2));
-}
diff --git a/Xisop/src/common/kernlib/string/strlen.c b/Xisop/src/common/kernlib/string/strlen.c
deleted file mode 100644 (file)
index 3bcca1b..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* $Id: strlen.c,v 1.2 2004/06/03 05:40:03 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-size_t strlen(const char *str)
-{
-    register const char *ptr = str;
-
-    /* Although this causes ptr to be increased even when 0 is reached,
-     * compilers generally generate better code.
-     * i.e. GCC2-m68k:  tstb %a0@+  vs  tstb %a0@  and  addql #1, %a0
-     * Matt
-     */
-    while (*ptr++ != '\0') ;
-
-    /* Don't forget to substract 1 */
-    return ((size_t)((ptr - 1) - str));
-}
diff --git a/Xisop/src/common/kernlib/string/strnchr.c b/Xisop/src/common/kernlib/string/strnchr.c
deleted file mode 100644 (file)
index a7ba5b8..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* $Id: strnchr.c,v 1.2 2004/06/03 05:40:04 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-char *strnchr(const char *str, int c, size_t max)
-{
-    if (max > 0) {
-       register const char *toptr;
-
-       for (toptr = str, toptr += max;
-               str < toptr && *str != '\0' && (int)*str != c; str++) ;
-
-       if (str == toptr || *str == '\0')
-           return NULL;
-
-       return (char *)str;
-    }
-
-    return NULL;
-}
diff --git a/Xisop/src/common/kernlib/string/strncmp.c b/Xisop/src/common/kernlib/string/strncmp.c
deleted file mode 100644 (file)
index de97198..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* $Id: strncmp.c,v 1.3 2004/06/03 05:40:04 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-int strncmp(const char *s1, const char *s2, size_t max)
-{
-    if (max > 0) {
-       register const char *toptr;
-
-       for (toptr = s1, toptr += max; s1 < toptr && *s1 != '\0' &&
-               *s2 != '\0' && *s1 == *s2; s1++, s2++) ;
-
-       return (s1 < toptr ?
-               ((int)((const unsigned char)*s1 - (const unsigned char)*s2)) :
-               0);
-    }
-
-    return 0;
-}
diff --git a/Xisop/src/common/kernlib/string/strnlen.c b/Xisop/src/common/kernlib/string/strnlen.c
deleted file mode 100644 (file)
index 231521e..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/* $Id: strnlen.c,v 1.2 2004/06/03 05:40:04 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-size_t strnlen(const char *str, size_t max)
-{
-    register const char *fptr, *tptr;
-
-    for (fptr = tptr = str, tptr += max; fptr < tptr && *fptr != '\0'; fptr++)
-       ;
-
-    return ((size_t)(fptr - str));
-}
diff --git a/Xisop/src/common/kernlib/string/strnrchr.c b/Xisop/src/common/kernlib/string/strnrchr.c
deleted file mode 100644 (file)
index a156119..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* $Id: strnrchr.c,v 1.2 2004/06/03 05:40:04 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-char *strnrchr(const char *str, int c, size_t max)
-{
-    register const char *toptr, *found;
-
-    for (found = NULL, toptr = str, toptr += max;
-           str < toptr && *str != '\0'; str++) {
-       if (*str == c)
-           found = str;
-    }
-
-    return (char *)found;
-}
diff --git a/Xisop/src/common/kernlib/string/strrchr.c b/Xisop/src/common/kernlib/string/strrchr.c
deleted file mode 100644 (file)
index d871c0e..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* $Id: strrchr.c,v 1.2 2004/06/03 05:40:04 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-char *strrchr(const char *str, int c)
-{
-    register const char *found;
-
-    for (found = NULL; *str != '\0'; str++) {
-       if (*str == c)
-           found = str;
-    }
-
-    return (char *)found;
-}
diff --git a/Xisop/src/common/kernlib/string/strspl.c b/Xisop/src/common/kernlib/string/strspl.c
deleted file mode 100644 (file)
index 0dac4a9..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* $Id: strspl.c,v 1.2 2004/06/03 05:40:04 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include <common/kernlib/string.h>
-
-
-
-/* Splits columns of a string delimited by sep, and fills
- * char **argv with pointers to each column. Returns the number of columns
- * that could be filled in. The supplied string IS modified. Note that two
- * contiguous separators cause empty entries to be filled in. An exception
- * consists of the last separator, which is ignored if nothing is found after
- * it.
- */
-int strspl(char **argv, char *str, int maxcols, char sep)
-{
-    register char *ptr, *ptr2;
-    int col;
-
-    for (col = 0, ptr = str; *ptr != '\0' && col < maxcols; ) {
-       for (ptr2 = ptr; *ptr != '\0' && *ptr != sep; ptr++) ;
-       if (*ptr != '\0')
-           *ptr++ = '\0';
-       argv[col++] = ptr2;
-    }
-
-    return col;
-}
-
-
diff --git a/Xisop/src/common/make.sh b/Xisop/src/common/make.sh
deleted file mode 100755 (executable)
index 962d2c7..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-
-# $Id: make.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ../makedefs.sh
-
-# Build kernlib
-show cd kernlib
-./make.sh
-show cd ..
-
-# Build kernel
-show cd kernel
-./make.sh
-show cd ..
diff --git a/Xisop/src/common/types.h b/Xisop/src/common/types.h
deleted file mode 100644 (file)
index c46da28..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/* $Id: types.h,v 1.6 2004/06/03 05:54:44 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef COMMON_TYPES_H
-#define COMMON_TYPES_H
-
-
-
-typedef unsigned char          u_int8_t;
-typedef signed char            int8_t;
-typedef unsigned short         u_int16_t;
-typedef signed short           int16_t;
-typedef unsigned long          u_int32_t;
-typedef signed long            int32_t;
-typedef unsigned long long     u_int64_t;
-typedef signed long long       int64_t;
-typedef int                    bool;
-typedef u_int32_t              size_t;
-typedef int32_t                        ssize_t;
-#define NULL                   ((void *)0)
-#define TRUE                   /* CONSTCOND */(1)
-#define FALSE                  /* CONSTCOND */(0)
-
-/* For code-embedded copyright and CVS/RCS ID strings */
-#define COPYRIGHT(x)           static const char _copyright[] = x
-#define RCSID(x)               static const char _rcsid[] = x
-
-
-/* Useful to o-align a value relative to v (sizes and pointers) */
-#define OALIGN_CEIL(v, o) \
-    ((((size_t)(v)) + (sizeof(o)) - 1) / (sizeof(o)) * (sizeof(o)))
-#define OALIGN_FLOOR(v, o)     ((size_t)(v) - (((size_t)(v) % sizeof(o))))
-
-/* Useful to byte align a value with supplied size */
-#define BALIGN_CEIL(v, s)      ((((size_t)(v)) + (s) - 1) / (s) * (s))
-#define BALIGN_FLOOR(v, s)     ((size_t)(v) - (((size_t)(v) % (s))))
-
-/* Import necessary processor-specific optimization macros */
-#include <processor/support.h>
-/* For network and host byte order of 16-bit and 32-bit types */
-#if defined(_ARCH_LITTLE_ENDIAN)
-#define BYTEORDER_NETWORK16            _bswap16
-#define BYTEORDER_HOST16               _bswap16
-#define BYTEORDER_NETWORK32            _bswap32
-#define BYTEORDER_HOST32               _bswap32
-#elif defined(_ARCH_BIG_ENDIAN)
-#define BYTEORDER_NETWORK16(w)         (w)
-#define BYTEORDER_HOST16(w)            (w)
-#define BYTEORDER_NETWORK32(w)         (w)
-#define BYTEORDER_HOST32(w)            (w)
-#else
-error "Endian not specified (_ARCH_LITTLE_ENDIAN | _ARCH_BIG_ENDIAN)";
-#endif
-/* Ensure that _ARCH_INT_BITS was defined */
-#ifndef _ARCH_INT_BITS
-error "Bits in an int (_ARCH_INT_BITS) not specified (8, 16, 32, 64)";
-#endif
-
-/* common/kernel/device.h */
-typedef struct devicenode      devicenode_t;
-typedef struct devicehandle    device_t;
-typedef struct iorequest       iorequest_t;
-
-/* common/kernel/exception.h */
-typedef u_int32_t              hookid_t;
-typedef struct _int_hook       hook_t;
-typedef struct _int_facility   facility_t;
-
-/* common/kernel/memory.h */
-typedef struct page            page_t;
-typedef struct mchunk          mchunk_t;
-typedef struct pool            pool_t;
-typedef struct ppool           ppool_t;
-typedef struct pnode           pnode_t;
-typedef struct mpool           mpool_t;
-typedef struct mnode           mnode_t;
-
-/* common/kernel/port.h */
-typedef struct port            port_t;
-typedef struct message         message_t;
-typedef struct mmessage                mmessage_t;
-
-/* common/kernel/scheduler.h */
-typedef struct rwlock          rwlock_t;
-
-/* common/kernel/signal.h */
-typedef int                    signum_t;
-typedef u_int32_t              sigmask_t;
-
-/* common/kernel/task.h */
-typedef struct task            task_t;
-typedef int8_t                 priority_t;
-
-/* common/kernlib/hash.h */
-typedef struct hashtable       hashtable_t;
-typedef struct hashnode                hashnode_t;
-
-
-#endif
diff --git a/Xisop/src/config.h b/Xisop/src/config.h
deleted file mode 100644 (file)
index 08cc233..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* $Id: config.h,v 1.5 2004/01/29 05:02:02 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef CONFIG_H
-#define CONFIG_H
-
-
-
-/* Flags which are possible to uncomment to compile in the kernel */
-
-#define DEBUG          4096
-#define STATISTICS
-
-
-
-#endif
diff --git a/Xisop/src/generic_makedefs.sh b/Xisop/src/generic_makedefs.sh
deleted file mode 100644 (file)
index a3bf722..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/sh
-
-# $Id: generic_makedefs.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-# These are various defaults which are used for the building process.
-# Change as required, and don't forget to create the ./port and ./processor
-# symbolic links to their respective directory.
-
-# Local non-cross building tools
-L_AR='ar qS'
-L_AS='as'
-L_CC='gcc'
-L_LD='ld'
-L_NM='nm'
-L_OBJDUMP='objdump'
-L_RANLIB='ranlib'
-L_STRIP='strip'
-L_CAT='cat'
-L_DD='dd'
-
-# Other general purpose tools
-L_RM='rm -f'
-L_LN='ln -s'
-L_SED='sed'
-L_ECHO='echo'
-L_LS='ls'
-
-show()
-{
-       # Only output to stderr, not stdout
-       $L_ECHO "$@" >&2
-       $@
-}
-
-# Deletes all .o files in a directory
-# $1 = directory
-cleanlib()
-{
-       show $L_RM $1/*.o
-}
diff --git a/Xisop/src/make.sh b/Xisop/src/make.sh
deleted file mode 100755 (executable)
index 3ae7f99..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/sh
-
-# $Id: make.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ./generic_makedefs.sh
-
-usage()
-{
-       $L_ECHO
-       $L_ECHO 'Usage: ./make.sh -t <target>'
-       $L_ECHO
-       $L_ECHO 'Available targets:'
-       $L_ECHO '- amiga'
-       $L_ECHO
-}
-
-while getopts t: f; do
-       case $f in
-       t)
-               case $OPTARG in
-               amiga)
-                       PROCESSOR='processors/m68k'
-                       PORT='ports/amiga'
-               ;;
-               *)
-                       $L_ECHO "Unknown target $OPTARG"
-               ;;
-               esac
-       ;;
-       *)
-               usage
-               exit 0
-       ;;
-       esac
-done
-if [ -z $PORT ] || [ -z $PROCESSOR ]; then
-       usage
-       exit 0
-fi
-
-./clean.sh
-show $L_LN $PROCESSOR processor
-show $L_LN $PORT port
-show $L_LN $PORT/makedefs.sh makedefs.sh
-show export SRCDIR=`pwd`
-
-# XXX Is this a bug? As port/ symbolic link goes down two levels, I have to
-# cd back two levels?
-
-# Build processor-specific support code to processor/ar/*.a
-show cd processor
-show ./make.sh
-
-# Build port-specific support code to port/ar/*.a
-show cd ../../port
-show ./make.sh
-
-# Build the portable common code to common/kernel/ar/*.a,
-# common/kernlib/ar/*.a and XXX ???
-# and link to global ELF relocatable kernel object xisop.o
-show cd ../../common
-show ./make.sh
-
-# Let the port-specific boot code create the kernel image
-show cd ../port/boot
-show ./make.sh
-
-show cd ..
diff --git a/Xisop/src/ports/amiga/boot/DOTuaerc b/Xisop/src/ports/amiga/boot/DOTuaerc
deleted file mode 100644 (file)
index b78e08c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-config_description=UAE
-x11.rom_path=./
-x11.floppy_path=./
-x11.hardfile_path=./
-x11.low_bandwidth=false
-x11.use_mitshm=false
-x11.hide_cursor=true
-32bit_blits=true
-use_gui=nowait
-use_debugger=false
-kickstart_rom_file=/home/mmondor/kick.rom
-floppy0=/home/mmondor/src/work/Xisop/src/ports/amiga/boot/xisop.adf
-floppy1=
-floppy2=
-floppy3=
-sound_output=none
-joyport0=mouse
-joyport1=kbd1
-kbd_lang=us
-immediate_blits=yes
-cpu_speed=max
-cpu_type=68000
-chipmem_size=2
-fastmem_size=4
-#filesystem=rw,System3.1:/data2/amiga/System3.1
-#filesystem=rw,Work:/data2/amiga/Work
-#filesystem=rw,ASM:/data2/amiga/asm
diff --git a/Xisop/src/ports/amiga/boot/README b/Xisop/src/ports/amiga/boot/README
deleted file mode 100644 (file)
index a088fde..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-DOTuaerc               ~/.uaerc used for testing and developping with UAE
-                       Amiga emulator
-
-xisop.adf              Actual Amiga bootable Xisop floppy image
-
-image.bin              Consists of the actual compiled kernel binary image
-image.o                        Useful for debugging, objdump -drw image.o
-bootf/bootf.bin                Compiled floppy boot sector image
-bootf/kernel.bin       Compiled floppy boot sector image + Xisop image
-
-config.h               File to modify depending on your Amiga model and
-                       kernel size, stack size, etc.
diff --git a/Xisop/src/ports/amiga/boot/bootf/bootf_c.c b/Xisop/src/ports/amiga/boot/bootf/bootf_c.c
deleted file mode 100644 (file)
index 7088e55..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/* $Id: bootf_c.c,v 1.2 2004/01/20 20:56:20 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* This used to be done by assembly code, it's however best to have a C
- * loader which could eventually perform fancy stuff, and relocation as well.
- * If the loader eventually gets too large to fit into the default boot block
- * size, this boot block can then simply serve to load another loader and
- * launch it.
- */
-
-
-
-#include <common/types.h>
-
-#include "../config.h"
-
-
-COPYRIGHT("\0\nXisop bootloader Copyright 2001-2003, Matthew Mondor, \
-All rights reserved.\n");
-
-
-
-/* CONFIGURATION */
-#define KERNSTART      1024    /* Start of kernel image on disk */
-#define READSIZE       4096    /* Block size for read/relocation (512 min) */
-
-
-
-#define MEMF_CHIP      0x0001
-#define MEMF_FAST      0x0002
-#define CMD_READ       2
-#define ALRT_NOMEM     0x00010001
-#define ALRT_RERR      0x14000001
-
-
-struct iostdreq {
-    u_int8_t pad[28];
-    u_int16_t command;
-    u_int8_t flags;
-    int8_t error;
-    u_int32_t actual, length;
-    void *data;
-    u_int32_t offset;
-};
-
-
-void *AllocMem(long, long);
-void *AllocAbs(long, void *);
-void FreeMem(void *, long);
-long DoIO(struct iostdreq *);
-void Alert(long, void *);
-
-void load(struct iostdreq *);
-
-
-
-void load(struct iostdreq *ioreq)
-{
-    void *buf = NULL, *readbuf = NULL;
-    bool ok = FALSE;
-
-    /* Allocate CHIP memory buffer to load disk blocks into */
-    if ((readbuf = AllocMem(READSIZE, MEMF_CHIP)) != NULL) {
-
-       if ((buf = AllocAbs(KERNSIZE + STACKSIZE, (void *)KERNADDR))
-               == (void *)KERNADDR) {
-           register u_int32_t offset, *addr, *toaddr;
-
-           /* Read image from disk starting at KERNSTART, upto
-            * KERNSTART + KERNSIZE, in blocks of READSIZE bytes, which we
-            * relocate to our kernel buffer on the fly in KERNADDR.
-            */
-           for (offset = KERNSTART, addr = buf, toaddr = buf + KERNSIZE;
-                   addr < toaddr; offset += READSIZE) {
-               register u_int32_t *raddr, *taddr;
-
-               /* Read a block */
-               ioreq->command = CMD_READ;
-               ioreq->length = READSIZE;
-               ioreq->data = readbuf;
-               ioreq->offset = offset;
-               if ((DoIO(ioreq)) != 0) {
-                   Alert(ALRT_RERR, load);
-                   for (;;) ;
-                   /* NOTREACHED */
-               }
-
-               /* Relocate block */
-               for (raddr = readbuf, taddr = readbuf + READSIZE;
-                       raddr < taddr; *addr++ = *raddr++) ;
-           }
-           ok = TRUE;
-       }
-       FreeMem(readbuf, READSIZE);
-       if (ok) {
-           void (*code)(u_int32_t *, size_t);
-
-           /* Jump to relocated code, passing it the supervisor stack */
-           code = (void *)KERNADDR;
-           code((u_int32_t *)STACKADDR, STACKSIZE);
-       }
-    }
-
-    Alert(ALRT_NOMEM, load);
-    for (;;) ;
-    /* NOTREACHED */
-}
diff --git a/Xisop/src/ports/amiga/boot/bootf/bootf_s.s b/Xisop/src/ports/amiga/boot/bootf/bootf_s.s
deleted file mode 100644 (file)
index 2937275..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/* $Id: bootf_s.s,v 1.2 2004/01/20 20:56:20 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-ExecBase =     0x0004
-
-
-.globl _start, AllocMem, AllocAbs, FreeMem, DoIO, Alert
-
-
-.text
-
-| AmigaOS boot header (checksum should be calculated after assembling)
-| This is actually loaded at 0x0020b660, the ROM jumps at 0x0020b66c.
-       .long   0x444f5300, 0x00000000, 0x00000000
-
-_start:
-
-| Loader code (startup leaves us with a6 to exec.lib and a1 to IOreq pointer)
-| Call our C load() function!
-|
-       movel   %a1, %sp@-
-       bsrl    load
-| NOTREACHED
-       addql   #4, %sp
-       rts
-
-
-| Amiga library of required function stubs for load() C function
-
-| [d0]void * = [-198]AllocMem([d0]long bytes, [d1]long reqs)
-|
-AllocMem:
-       moveml  %a6/%d1-%d0, %sp@-
-       moveal  ExecBase:w, %a6
-       movel   %sp@(16), %d0
-       movel   %sp@(20), %d1
-       jsr     %a6@(-198)
-       moveal  %d0, %a0
-       moveml  %sp@+, %d0-%d1/%a6
-       rts
-
-| [d0]void * = [-204]AllocAbs([d0]long bytes, [a1]void *addr)
-|
-AllocAbs:
-       moveml  %a1/%a6/%d0, %sp@-
-       moveal  ExecBase:w, %a6
-       movel   %sp@(16), %d0
-       moveal  %sp@(20), %a1
-       jsr     %a6@(-204)
-       moveal  %d0, %a0
-       moveml  %sp@+, %d0/%a6/%a1
-       rts
-
-| void [-210]FreeMem([a1]memptr, [d0]bytesize)
-|
-FreeMem:
-       moveml  %a1/%a6/%d0, %sp@-
-       moveal  ExecBase:w, %a6
-       moveal  %sp@(16), %a1
-       movel   %sp@(20), %d0
-       jsr     %a6@(-210)
-       moveml  %sp@+, %d0/%a6/%a1
-       rts
-
-| [d0] = [-456]DoIO([a1]struct IORequest *)
-|
-DoIO:
-       moveml  %a1/%a6, %sp@-
-       moveal  ExecBase:w, %a6
-       moveal  %sp@(12), %a1
-       jsr     %a6@(-456)
-       moveml  %sp@+, %a6/%a1
-       rts
-
-| void [-108]Alert([d7]long alertNum,[a5]char *flags)
-|
-Alert:
-       moveml  %d7/%a5-%a6, %sp@-
-       moveal  ExecBase:w, %a6
-       movel   %sp@(16), %d7
-       moveal  %sp@(20), %a5
-       jsr     %a6@(-108)
-       moveml  %sp@+, %a6-%a5/%d7
-       rts
diff --git a/Xisop/src/ports/amiga/boot/bootf/bootf_script.ld b/Xisop/src/ports/amiga/boot/bootf/bootf_script.ld
deleted file mode 100644 (file)
index b422db9..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-OUTPUT_FORMAT("binary", "binary", "binary")
-OUTPUT_ARCH(m68k)
-
-ENTRY(_start)
-
-SECTIONS {
-       . = 0x0020b660;
-       .text : {
-               *(.text)
-               *(.rodata)
-               *(.data)
-               *(.bss)
-       }
-}
diff --git a/Xisop/src/ports/amiga/boot/clean.sh b/Xisop/src/ports/amiga/boot/clean.sh
deleted file mode 100755 (executable)
index 79f30ca..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-# $Id: clean.sh,v 1.2 2004/01/20 20:56:20 mmondor Exp $
-
-. ../../../generic_makedefs.sh
-
-show $L_RM image.bin image.o init.o
-show $L_RM tools/aosbblock tools/dumpkern tools/config
-show $L_RM bootf/bootf_s.o bootf/bootf_c.o bootf/bootf.o bootf/bootf.bin
-show $L_RM bootf/kern.bin xisop.adf
diff --git a/Xisop/src/ports/amiga/boot/config.h b/Xisop/src/ports/amiga/boot/config.h
deleted file mode 100644 (file)
index 537e947..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* $Id: config.h,v 1.1 2004/01/20 20:56:20 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* Until proper memory auto-detection is made, this file contains the general
- * information needed to setup the supervisor stack and kernel image location,
- * as well as the available RAM.
- * This currently assumes that 4 megs of FAST RAM are located from
- * 0x00200000 to 0x005fffff (Card 1, Zorro II), and that 2 megs of CHIP RAM
- * are found from 0x00001000 to 0x001fffff.
- * All these numbers should be a multiple of 4096 bytes.
- */
-
-
-
-/* CONFIGURATION */
-
-/* Size of kernel image to read from disk, in bytes */
-#define KERNSIZE       65536
-
-/* Size of kernel supervisor stack, in bytes */
-#define STACKSIZE      8192
-
-/* Boundaries of FAST RAM */
-#define FMEM_START     0x00200000
-#define FMEM_END       0x00600000
-
-/* Boundaries of CHIP RAM */
-#define CMEM_START     0x00001000
-#define CMEM_END       0x00200000
-
-
-/* These are useful results, used by boot/bootf/bootf_c.c, boot/init.c
- * and boot/tools/config.c
- */
-#define STACKADDR      (FMEM_END - STACKSIZE)
-#define KERNADDR       (STACKADDR - KERNSIZE)
-#define FPOOLADDR      (FMEM_START)
-#define FPOOLSIZE      (KERNADDR - FMEM_START - 1)
-#define CPOOLADDR      (CMEM_START)
-#define CPOOLSIZE      (CMEM_END - CMEM_START - 1)
diff --git a/Xisop/src/ports/amiga/boot/image_script.ld b/Xisop/src/ports/amiga/boot/image_script.ld
deleted file mode 100644 (file)
index 8ee2279..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-OUTPUT_FORMAT("binary", "binary", "binary")
-OUTPUT_ARCH(m68k)
-
-ENTRY(_start)
-
-SECTIONS {
-       .text : {
-               *(.text)
-               *(.rodata)
-               *(.data)
-               *(.bss)
-       }
-}
diff --git a/Xisop/src/ports/amiga/boot/init.c b/Xisop/src/ports/amiga/boot/init.c
deleted file mode 100644 (file)
index 1e59866..0000000
+++ /dev/null
@@ -1,590 +0,0 @@
-/* $Id: init.c,v 1.7 2004/01/20 21:26:48 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* This code entry point consist of _start() which is called by the boot
- * loader. We setup the supervisor stack pointer and then jump to _init(),
- * which sets up the various port-specifics for Xisop, and finally launches
- * Xisop itself calling main(). See the Xisop documentation for more
- * information on what port-specific code has to provide in it's
- * initialization and support.h.
- */
-
-
-
-#include <common/types.h>
-#include <processors/m68k/support.h>
-#include <ports/amiga/support.h>
-#include <common/kernel/main.h>
-#include <common/kernel/memory.h>
-#include <common/kernel/exception.h>
-#include <common/kernel/syscall.h>
-#include <common/kernel/task.h>
-#include <common/kernel/port.h>
-
-#include "config.h"
-
-
-
-/* Entry point */
-void _start(u_int32_t *, size_t);
-
-/* Our initialization functions */
-static void _init(void);
-static void _disable_interrupts(void);
-static void _stop_floppy_motor(void);
-static void _init_memory(void);
-static void _init_syscalls(void);
-static void _enable_keyboard_interrupt(void);
-static void _enable_vblank_interrupt(void);
-static void _init_scheduler(void);
-static void _init_screen(void);
-
-/* C exception handlers */
-void _icatch1(u_int16_t);
-void _icatch2(u_int16_t);
-void _icatch3(u_int16_t);
-void _icatch4(u_int16_t);
-void _icatch5(u_int16_t);
-void _tcatch(int);
-void _ecatch(int);
-
-
-/* Port-specific port-initialization, to attach our port-specific shared
- * libraries and launch our port-specific tasks
- */
-struct initmsg {
-    message_t node;
-    u_int16_t color;
-};
-
-struct taskarg {
-    u_int16_t color;
-    u_int32_t rounds;
-};
-
-static int _task_color_server(void *, void *);
-static int _task_color_client(void *, void *);
-static void _keyboard_hook(hookid_t, int, void *);
-void _panic(u_int16_t);
-
-
-
-/* Used to ensure that only the first exception occurs */
-static _rlock_t elock;
-
-
-
-/* The role of this function is to go in supervisor mode, set the supervisor
- * stack, then call init().
- */
-void _start(u_int32_t *ssp, size_t sz) {
-    _supervisor(ssp, sz, _init);
-    /* NOTREACHED */
-}
-
-
-/* Main port-specific initialization */
-static void _init(void)
-{
-    /* So that ecatch() cannot recurse */
-    _rlock_init(&elock);
-
-    _disable_interrupts();
-    _stop_floppy_motor();
-
-    memory_init();             /* MI function */
-    _init_memory();
-
-    facilities_init();
-
-    _init_exceptions();
-
-    _init_syscalls();
-
-    _enable_keyboard_interrupt();
-    _enable_vblank_interrupt();
-    _init_scheduler();
-    _init_screen();
-
-    /* It is necessary to call this other MI function now, which internally
-     * will enable interrupts when safe to do so, which should have been
-     * disabled all along initialization.
-     */
-    xisop_init();
-
-    /* We finally can switch to usermode and jump to MI main().
-     * _usermode() m68k-specific function uses 1024 bytes on the
-     * current supervisor stack to create a user stack, and jumps to
-     * the specified function in user mode using that small stack.
-     */
-    _usermode(main);
-
-    /* NOTREACHED */
-}
-
-
-static void _disable_interrupts(void)
-{
-    /* Turn off scheduling, interrupts and DMA channels */
-    Forbid();
-    /* Disable interrupts */
-    _splhigh();
-    CUSTOM->INTENA = INTENA_CLRALL;
-    CUSTOM->INTREQ = INTREQ_CLRALL;
-    /* Disable DMA */
-    CUSTOM->DMACON = DMACON_CLRALL;
-    /* Disable CIA interrupt generation */
-    CIA_A->ICR = CIA_ICR_CLRALL;
-    CIA_B->ICR = CIA_ICR_CLRALL;
-}
-
-
-static void _stop_floppy_motor(void)
-{
-    /* Stop floppy0 drive motor */
-    CIA_B->PRB &= ~CIAB_PRB_FLOP0;     /* Select */
-    CIA_B->PRB |= CIAB_PRB_FMOTOR;     /* Command */
-}
-
-
-static void _init_memory(void)
-{
-    mchunk_t *mchunk;
-
-    /* Initialize memory system, facilities_init() needs this to be done.
-     * XXX Some effort should be made to better detect the available memory,
-     * but at least it's easy to fix for each system type right now.
-     * The file to modify consists of ../config.h
-     */
-    mchunk = mchunk_init((void *)FPOOLADDR, FPOOLSIZE);
-    mchunk_attach(_MEM_FAST, mchunk);
-    mchunk = mchunk_init((void *)CPOOLADDR, CPOOLSIZE);
-    mchunk_attach(_MEM_CHIP, mchunk);
-}
-
-
-static void _init_syscalls(void)
-{
-    CUSTOM->INTENA = INT_SETCLR | INT_SOFT;
-}
-
-
-static void _enable_keyboard_interrupt(void)
-{
-    /* Enable keyboard interrupts */
-    CIA_A->CRA = CIA_CRA_START | CIA_CRA_INMODE;
-    CIA_A->ICR = CIA_ICR_SETCLR | CIA_ICR_SERDONE;
-    CUSTOM->INTENA = INT_SETCLR | INT_CIAA;
-}
-
-
-static void _enable_vblank_interrupt(void)
-{
-    /* Enable vertical blank interrupt */
-    CUSTOM->INTENA = INT_SETCLR | INT_VBLANK;
-}
-
-
-/* Enable CIA-B TimerA interrupt for scheduler, which has high priority */
-static void _init_scheduler(void)
-{
-    u_int8_t *p;
-    u_int16_t v;
-
-    /* Evaluate latch value to use for scheduler frequency */
-    v = (u_int16_t)(CIA_COUNTSPEED / SCHEDTIMER_HZ);
-    p = (u_int8_t *)&v;
-    /* Stop timer and set latch */
-    CIA_B->CRA = 0x00;
-    CIA_B->TAHI = p[0];
-    CIA_B->TALO = p[1];
-    /* Start and order to load latch value, in contiguous mode */
-    CIA_B->CRA = CIA_CRA_START | CIA_CRA_LOAD;
-    CIA_B->ICR = CIA_ICR_SETCLR | CIA_ICR_TIMA0;
-    /* Enable CIA-B interrupts */
-    CUSTOM->INTENA = INT_SETCLR | INT_CIAB;
-}
-
-
-/* Setup our Amiga Xisop console screen */
-/* XXX I have two choices here. I could use a 16 color screen and emulate
- * ANSI-BBS colors, or just use a two color one and use my very small fonts.
- * in the second case, I could still support a few control codes.
- */
-static void _init_screen(void)
-{
-    u_int16_t s;
-
-    /* I need to allocate/initialize a bitmap/bitplane, as well as
-     * chip memory for the copper list.
-     */
-    s = asplvblank();
-    /* Screen size and position configuration */
-    CUSTOM->DDFSTRT = 0x3C;
-    CUSTOM->DDFSTOP = 0xD4;
-    CUSTOM->DIWSTRT = 0x2C81;
-    CUSTOM->DIWSTOP = 0xF4C1;
-    CUSTOM->CLXCON = 0x0000;
-    /* Enable bitplane and copper DMA */
-    CUSTOM->DMACON = DMACON_SETCLR | DMACON_BLITTER /*| DMACON_COPPER*/;
-    asplx(s);
-}
-
-
-/* These consist of the various interrupt handlers corresponding to each
- * of the 6 maskable hardware interrupt levels. Using _spl*() one can set the
- * current task level which may not be interrupted by every lower level.
- * <intreq> may be used to evaluate the cause of the interrupt.
- */
-
-/* ARGSUSED */
-void _icatch1(u_int16_t intreq)
-{
-    _ipl_t x;
-
-    x = _spl1();
-    if (intreq & INT_SOFT) {
-       /* Software interrupt */
-    }
-    if (intreq & INT_FLOPBLCK) {
-       /* Floppy disk block done interrupt */
-       facility_exechooks(_FACILITY_FLOPPYBLOCK, 0);
-    }
-    if (intreq & INT_SERTBE) {
-       /* Serial RS-232 trasmit buffer empty interrupt */
-       facility_exechooks(_FACILITY_SERIALTBE, 0);
-    }
-    _splx(x);
-}
-
-void _icatch2(u_int16_t intreq)
-{
-    _ipl_t x;
-
-    x = _spl2();
-    if (intreq & INT_CIAA) {
-       /* CIA-A or expansion bus pin 19 interrupt */
-       u_int8_t icrmask = CIA_A->ICR;
-
-       /* CIA-A TimerA available.
-        * CIA-A TimerB used for keyboard.
-        * CIA-A TOD counter available.
-        */
-       if (icrmask & CIA_ICR_TIMB0) {
-           /* CIA-A TimerB reached 0. If used in continuous we only need
-            * to react, otherwise we also should reload a latch value back.
-            * This counts at a rate of 715909/second for NTSC and
-            * 709379/second for PAL.
-            */
-           facility_exechooks(_FACILITY_CIATIMB0, 0);
-       }
-       if (icrmask & CIA_ICR_SERDONE) {
-           /* Keyboard intput interrupt */
-           u_int8_t c;
-
-           c = CIA_A->SDR;
-           facility_exechooks(_FACILITY_KEYBOARD, (int)c);
-       }
-    }
-    _splx(x);
-}
-
-void _icatch3(u_int16_t intreq)
-{
-    _ipl_t x;
-
-    x = _spl3();
-    if (intreq & INT_COPPER) {
-       /* Copper processor generated interrupt */
-       facility_exechooks(_FACILITY_COPPER, 0);
-    }
-    if (intreq & INT_VBLANK) {
-       /* Vertical blank (raster) interrupt */
-       facility_exechooks(_FACILITY_VBLANK, 0);
-    }
-    if (intreq & INT_BLITRDY) {
-       /* Blitter done/ready interrupt */
-       facility_exechooks(_FACILITY_BLITTERREADY, 0);
-    }
-    _splx(x);
-}
-
-/* ARGSUSED */
-void _icatch4(u_int16_t intreq)
-{
-    _ipl_t x;
-
-    x = _spl4();
-    if (intreq & INT_AUDIO0) {
-       /* DMA done for audio channel 0 interrupt */
-       facility_exechooks(_FACILITY_AUDIO, 0);
-    }
-    if (intreq & INT_AUDIO1) {
-       /* DMA done for audio channel 1 interrupt */
-       facility_exechooks(_FACILITY_AUDIO, 1);
-    }
-    if (intreq & INT_AUDIO2) {
-       /* DMA done for audio channel 2 interrupt */
-       facility_exechooks(_FACILITY_AUDIO, 2);
-    }
-    if (intreq & INT_AUDIO3) {
-       /* DMA done for audio channel 3 interrupt */
-       facility_exechooks(_FACILITY_AUDIO, 3);
-    }
-    _splx(x);
-}
-
-/* ARGSUSED */
-void _icatch5(u_int16_t intreq)
-{
-    _ipl_t x;
-
-    x = _spl5();
-    if (intreq & INT_SERRBF) {
-       /* Serial RS-232 read buffer full interrupt */
-       facility_exechooks(_FACILITY_SERIALRBF, 0);
-    }
-    if (intreq & INT_FLOPSYNC) {
-       /* Floppy disk sync pattern found interrupt */
-       facility_exechooks(_FACILITY_FLOPPYSYNC, 0);
-    }
-    _splx(x);
-}
-
-/* Level 6 handled by assembly code */
-
-
-/* And generic C trap handler to catch remaining trap vectors (0 and 1 are
- * used by the system calls and _yield(), respectively.
- */
-void _tcatch(int vector)
-{
-    _ipl_t x;
-
-    x = _splhigh(); /* XXX */
-    facility_exechooks(_FACILITY_TRAP, vector);
-    _splx(x);
-}
-
-
-/* A hack to display the exception vector number using raster lines */
-void _ecatch(int vector)
-{
-    static u_int16_t ecolors[2] = {0x0F00, 0x0A00};
-    register bool col = FALSE;
-
-    if (_rlock_try(&elock)) {
-       _splhigh();
-       for (;;) {
-           register int i;
-
-           for (i = 0; i < vector; i++) {
-               CUSTOM->COLOR[0] = ecolors[col];
-               ldelay(2);
-               CUSTOM->COLOR[0] = 0x0000;
-               ldelay(2);
-           }
-           ldelay(8);
-           col = !col;
-       }
-    }
-    for (;;)
-       _idle();
-}
-
-
-
-/* Function we supply to Xisop which calls it to allow us to initialize
- * our port-specific shared libraries and tasks.
- */
-void _port_init(void)
-{
-    register task_t *task;
-
-    if ((task = task_alloc(_task_color_server, NULL, NULL, 0, 4096, TF_KERNEL))
-           != NULL)
-       task_start(task);
-    else
-       _panic(0x0F00); /* Red */
-}
-
-
-
-/* These are our port-specific tasks */
-
-/* ARGSUSED */
-static int _task_color_server(void *res, void *args)
-{
-    port_t *port;
-
-    /* Create our public port */
-    if ((port = port_create("COLOR")) != NULL) {
-       struct taskarg targ[3];
-       task_t *task;
-       hookid_t kbdhook;
-
-       /* Setup an interrupt handler (only for fun) */
-       kbdhook = hook_attach(_FACILITY_KEYBOARD, 10, 0, _keyboard_hook, NULL);
-
-       /* Start our tasks. As these require our port to communicate through,
-        * note that we created it first.
-        */
-       targ[0].color = 0x00F0;
-       targ[0].rounds = 6000;
-       if ((task = task_alloc(_task_color_client, NULL, &targ[0], 0, 4096,
-                       TF_SHARED)) != NULL)
-           task_start(task);
-       targ[1].color = 0x00C0;
-       targ[1].rounds = 4000;
-       if ((task = task_alloc(_task_color_client, NULL, &targ[1], 0, 4096,
-                       TF_SHARED)) != NULL)
-           task_start(task);
-       targ[2].color = 0x0090;
-       targ[2].rounds = 2000;
-       if ((task = task_alloc(_task_color_client, NULL, &targ[2], 0, 4096,
-                       TF_SHARED)) != NULL)
-           task_start(task);
-
-       /* Main loop. All we do is listen for requests via our port, in the
-        * form of messages. When we get one, display the requested color,
-        * and reply. This task should be in STATE_WAIT most of the time,
-        * and only awakens to answer requests then goes back to sleep.
-        */
-       for (;;) {
-           port_t *ports[] = {
-               port
-           };
-           register struct initmsg *msg = NULL;
-
-           /* Black to show that we are sleeping */
-           CUSTOM->COLOR[0] = 0x0000;
-           ldelay(1);
-           if ((port_wait(ports, 1, NULL)) == port) {
-               /* We could use while () here instead of if (), however this
-                * gives a better demonstration. When the screen eventually
-                * gets purple, all tasks are sleeping (init, reaper and
-                * this task, since our three children have died already).
-                * If we use while (), we never go in sleep mode, since there
-                * are several feeders and they are of equal priority than
-                * us.
-                */
-               if ((msg = (struct initmsg *)port_get(port)) != NULL) {
-                   CUSTOM->COLOR[0] = msg->color;
-                   if (!port_reply((message_t *)msg))
-                       _panic(0x0F00); /* Red */
-               }
-           } else
-               _panic(0x0FF0); /* Yellow */
-       }
-
-       port = port_destroy(port);
-    }
-
-    _panic(0x0FFF);    /* White */
-    /* NOTREACHED */
-    return 0;
-}
-
-
-/* ARGSUSED */
-static int _task_color_client(void *res, void *args)
-{
-    port_t *rport;
-
-    /* Create our reply port */
-    if ((rport = port_create(NULL)) != NULL) {
-       port_t *sport;
-
-       /* Locate task_init()'s public port */
-       if ((sport = port_find("COLOR")) != NULL) {
-           struct initmsg msg;
-           port_t *ports[] = {
-               rport
-           };
-           struct taskarg *targ = args;
-           register u_int32_t rounds = targ->rounds;
-
-           msg.color = targ->color;
-           /* Send coloring requests via the public COLOR port.
-            * For each request we wait for a reply, and then continue.
-            * This task runs most of the time, only sleeping when waiting
-            * for a result from the slave task.
-            */
-           for (;rounds > 0; rounds--) {
-               if (port_send(sport, rport, (message_t *)&msg)) {
-                   if ((port_wait(ports, 1, NULL)) == rport) {
-                       /* Just get rid of messages since we don't need to
-                        * verify a result code.
-                        */
-                       port_flush(rport);
-                   } else
-                       _panic(0x0FF0); /* Yellow */
-               } else
-                   _panic(0x0F00);     /* Red */
-           }
-       }
-
-       rport = port_destroy(rport);
-    }
-
-    return 0;
-}
-
-
-/* Used in the case of a fatal error we catch */
-void _panic(u_int16_t color)
-{
-    sched_disable();
-    sys_int_disable();
-    for (;;) {
-       CUSTOM->COLOR[0] = color;
-       ldelay(2);
-       CUSTOM->COLOR[0] = 0x0000;
-       ldelay(2);
-    }
-    /* NOTREACHED */
-}
-
-
-/* Mainly used as a test for now */
-/* ARGSUSED */
-static void _keyboard_hook(hookid_t hookid, int reason, void *udata)
-{
-    register u_int16_t col = 0;
-
-    /* Just display a color corresponding to the keyboard code */
-    col |= reason; col <<= 8; col |= reason;
-    CUSTOM->COLOR[0] = col;
-}
diff --git a/Xisop/src/ports/amiga/boot/make.sh b/Xisop/src/ports/amiga/boot/make.sh
deleted file mode 100755 (executable)
index 820e10d..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-
-# $Id: make.sh,v 1.2 2004/01/20 20:56:20 mmondor Exp $
-
-. ../../../makedefs.sh
-
-# Create tools
-show $L_CC -Wall -o tools/aosbblock tools/aosbblock.c
-show $L_CC -Wall -o tools/dumpkern tools/dumpkern.c
-show $L_CC -Wall -o tools/config tools/config.c
-KERNADDR=$(tools/config)
-
-# Create kernel image
-show $C_COMPC -I$SRCDIR init.c
-A=`$L_LS ../../../common/kernel/ar/*.a ../ar/*.a ../../../processor/ar/*.a ../../../common/kernlib/ar/*.a`
-show $C_LD -nostdlib -e _start -Ttext $KERNADDR -o image.o init.o $A
-show $C_LD -T image_script.ld -Ttext $KERNADDR -nostdlib -o image.bin init.o $A
-
-# Create bootblock loader
-show $C_COMPS -I$SRCDIR -o bootf/bootf_s.o bootf/bootf_s.s
-show $C_COMPC -I$SRCDIR -o bootf/bootf_c.o bootf/bootf_c.c
-show $C_LD -nostdlib -r -Ttext 0x0020b660 -o bootf/bootf.o bootf/bootf_s.o bootf/bootf_c.o
-show $C_LD -T bootf/bootf_script.ld -nostdlib -o bootf/bootf.bin bootf/bootf.o
-show tools/aosbblock bootf/bootf.bin
-
-# Create bootable floppy image
-show $L_CAT bootf/bootf.bin image.bin >bootf/kern.bin
-show $L_DD if=/dev/zero of=xisop.adf bs=901120 count=1
-show tools/dumpkern xisop.adf bootf/kern.bin
-
-$L_ECHO ===
-$L_ECHO The floppy image should be $SRCDIR/ports/amiga/boot/xisop.adf
-$L_ECHO ===
diff --git a/Xisop/src/ports/amiga/boot/tools/aosbblock.c b/Xisop/src/ports/amiga/boot/tools/aosbblock.c
deleted file mode 100644 (file)
index 95cbeae..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/* $Id: aosbblock.c,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* 
- * Fixes a bootblock to be 1024 bytes in size, and sets it's AmigaOS checksum
- */
-
-
-
-#include <sys/types.h>
-#include <stdio.h>
-
-
-
-int main(int, char **);
-u_int32_t checksum(u_int32_t *, int);
-
-
-
-int main(int argc, char **argv)
-{
-    FILE *fh;
-    u_int32_t lblock[256];
-    int i;
-    char *block = (char *)lblock;
-
-    if (argc == 2) {
-
-       if ((fh = fopen(argv[1], "rb"))) {
-           /* First make sure to 0 pad block, then load block */
-           for (i = 0; i < 256; i++)
-               lblock[i] = 0;
-           fread(block, 1, 1024, fh);
-           fclose(fh);
-       } else {
-           printf("could not open file \"%s\" for reading\n", argv[1]);
-           exit(-1);
-       }
-
-       /* Calculate block checksum and fix it */
-       lblock[1] = 0;
-       lblock[1] = htonl(0xFFFFFFFF - checksum(lblock, 256));
-
-       /* Write back file over old one */
-       if ((fh = fopen(argv[1], "wb"))) {
-           fwrite(block, 1, 1024, fh);
-           fclose(fh);
-       } else {
-           printf("could not open file \"%s\" for writing\n", argv[1]);
-           exit(-1);
-       }
-
-    } else {
-       printf("usage: aosbblock <file>\n");
-       exit(-1);
-    }
-
-    exit(0);
-}
-
-
-u_int32_t checksum(u_int32_t *block, int size)
-{
-    u_int32_t sum, lastsum;
-    int i;
-
-    for (sum = 0, i = 0; i < size; i++) {
-       lastsum = sum;
-       sum += ntohl(block[i]);
-       if (sum < lastsum)
-           ++sum;
-    }
-
-    return sum;
-}
diff --git a/Xisop/src/ports/amiga/boot/tools/config.c b/Xisop/src/ports/amiga/boot/tools/config.c
deleted file mode 100644 (file)
index 116feca..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* $Id: config.c,v 1.1 2004/01/20 20:56:20 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* This program is useful to know the proper address to use in image_script.ld
- * and make.sh for building the kernel image.
- */
-
-
-
-#include <stdio.h>
-#include "../config.h"
-
-
-
-int main(void);
-
-
-
-int main(void)
-{
-    printf("0x%08x\n", KERNADDR);
-    /*
-    printf("Supervisor stack location (0x%08x bytes): 0x%08x\n",
-           STACKSIZE, STACKADDR);
-    printf("Kernel image location (0x%08x bytes): 0x%08x\n",
-           KERNSIZE, KERNADDR);
-    printf("Usable multipurpose RAM: (0x%08x bytes) 0x%08x\n",
-           POOLSIZE, POOLADDR);
-     */
-
-    return 0;
-}
diff --git a/Xisop/src/ports/amiga/boot/tools/dumpkern.c b/Xisop/src/ports/amiga/boot/tools/dumpkern.c
deleted file mode 100644 (file)
index b39abe0..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/* $Id: dumpkern.c,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* Simple program to allow to dump a kernel image over an existing file
- * (ususally to serve as a virtual floppy for bochs or to create
- * floppy image files), without changing the size of the file.
- */
-
-
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-
-
-
-#define BUFSIZE        4096
-
-
-
-int main(int, char **);
-
-
-
-int main(int argc, char **argv)
-{
-    if (argc == 3) {
-       int ffd, kfd;
-
-       if ((ffd = open(argv[1], O_RDWR)) != -1) {
-           if ((kfd = open(argv[2], O_RDONLY)) != -1) {
-               char buf[BUFSIZE];
-               size_t len;
-
-               while ((len = read(kfd, buf, BUFSIZE)) > 0)
-                   if ((write(ffd, buf, len)) != len) {
-                       fprintf(stderr, "Error writing\n");
-                       break;
-                   }
-               close(kfd);
-           } else fprintf(stderr, "Cannot open kernel file '%s'\n", argv[2]);
-           close(ffd);
-       } else fprintf(stderr, "Cannot open disk file '%s'\n", argv[1]);
-    } else fprintf(stderr, "Usage: dumpkern <file> <kernel>\n");
-
-    exit(0);
-}
diff --git a/Xisop/src/ports/amiga/clean.sh b/Xisop/src/ports/amiga/clean.sh
deleted file mode 100755 (executable)
index 7058be2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-# $Id: clean.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ../../generic_makedefs.sh
-
-show $L_RM support_s.o support_c.o ar/*.a
diff --git a/Xisop/src/ports/amiga/make.sh b/Xisop/src/ports/amiga/make.sh
deleted file mode 100755 (executable)
index 9d58b03..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-# $Id: make.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ../../makedefs.sh
-
-show $C_COMPS -I$SRCDIR support_s.s
-show $C_COMPC -I$SRCDIR support_c.c
-show $C_AR ar/support.a support_s.o support_c.o
-show $C_RANLIB ar/support.a
diff --git a/Xisop/src/ports/amiga/makedefs.sh b/Xisop/src/ports/amiga/makedefs.sh
deleted file mode 100644 (file)
index b1eef0c..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/bin/sh
-
-# $Id: makedefs.sh,v 1.2 2003/12/27 00:01:55 mmondor Exp $
-
-# These are various defaults which are used for the building process.
-# Change as required, and don't forget to create the ./port and ./processor
-# symbolic links to their respective directory.
-
-# Local non-cross building tools
-L_AR='ar qS'
-L_AS='as'
-L_CC='gcc'
-L_LD='ld'
-L_NM='nm'
-L_OBJDUMP='objdump'
-L_RANLIB='ranlib'
-L_STRIP='strip'
-L_CAT='cat'
-L_DD='dd'
-
-# Cross building tools (set to same values as L_* if wanted)
-C_PREFIX='/usr/src/tools/bin'
-C_AR="$C_PREFIX/m68k--netbsdelf-ar qS"
-C_AS="$C_PREFIX/m68k--netbsdelf-as"
-C_CC="$C_PREFIX/m68k--netbsdelf-gcc"
-C_LD="$C_PREFIX/m68k--netbsdelf-ld"
-C_NM="$C_PREFIX/m68k--netbsdelf-nm"
-C_OBJDUMP="$C_PREFIX/m68k--netbsdelf-objdump"
-C_RANLIB="$C_PREFIX/m68k--netbsdelf-ranlib"
-C_STRIP="$C_PREFIX/m68k--netbsdelf-strip"
-
-# Other general purpose tools
-L_RM='rm -f'
-L_LN='ln -s'
-L_SED='sed'
-L_ECHO='echo'
-L_LS='ls'
-
-# Command to compile a C module using the cross-compiler
-#C_COMPC="$C_CC -Wall -ffreestanding -nostdinc -m68000 -O2 -fno-function-cse -fomit-frame-pointer -c"
-C_COMPC="$C_CC -Wall -ffreestanding -nostdinc -m68000 -O2 -fno-function-cse -fomit-frame-pointer -c"
-# And to compile an assembly module using the cross-assembler
-C_COMPS="$C_CC -Wall -ffreestanding -nostdinc -m68000 -c"
-
-show()
-{
-       # Only output to stderr, not stdout
-       $L_ECHO "$@" >&2
-       $@
-}
-
-# Useful to compile all .c and .s files in a directory to .o modules
-# $1 = directory
-buildlib()
-{
-       for i in `$L_LS $1/*.s 2>/dev/null`; do
-               DEST=`$L_ECHO $i | $L_SED 's/\.s/\.o/'`
-               show $C_COMPS -I$SRCDIR -o $DEST $i
-       done
-       for i in `$L_LS $1/*.c 2>/dev/null`; do
-               DEST=`$L_ECHO $i | $L_SED 's/\.c/\.o/'`
-               show $C_COMPC -I$SRCDIR -o $DEST $i
-       done
-}
-
-# Deletes all .o files in a directory
-# $1 = directory
-cleanlib()
-{
-       show $L_RM $1/*.o
-}
diff --git a/Xisop/src/ports/amiga/support.h b/Xisop/src/ports/amiga/support.h
deleted file mode 100644 (file)
index bdd609b..0000000
+++ /dev/null
@@ -1,467 +0,0 @@
-/* $Id: support.h,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2001-2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* 
- * This code was not derived from original AmigaOS headerfiles, but rather
- * made comparing informations from various books I already had at home,
- * such as "Mapping the Amiga", "La Bible de l'Amiga", and "Amiga Intern".
- *
- * Matt
- */
-
-
-
-#ifndef AMIGA_SUPPORT_H
-#define AMIGA_SUPPORT_H
-
-
-
-#include <common/types.h>
-
-
-
-/* Adapt this as required for NTSC or PAL Amigas */
-
-/* CIA TimerA and TimerB count this amount of ticks per second */
-/* NTSC */
-/*#define CIA_COUNTSPEED 715909*/
-/* PAL */
-#define CIA_COUNTSPEED 709379
-
-
-
-/* The Amiga has two CIA chips, each CIA supports two 8-bit parallel ports
- * and one serial port. Each CIA chip also has two timers. Amiga also has
- * various custom chips (Agnus, Denise, Paula, Ramsey, the copper parallel
- * coprocessor)...
- *
- * The use of the CIA timers and counters is as follows:
- * - CIA-A TOD counter available
- * - CIA-A TimerA used for keyboard timing
- * - CIA-A TimerB available
- * - CIA-B TOD counter available
- * - CIA-B TimerA available, we use it for the Xisop scheduler interrupt.
- * - CIA-B TimerB available
- *
- * Xisop kernel itself may not need to use all those registers, however
- * devices may, and will be able to use this same headerfile.
- */
-
-#define CIA_A  ((volatile CIA *)0x00BFE001)
-#define CIA_B  ((volatile CIA *)0x00BFD000)
-#define CUSTOM ((volatile CUST *)0x00DFF000)
-
-
-/* Each of the two CIAs have this structure (8520 chip as mapped in Amiga) */
-typedef struct CIA {
-    volatile u_int8_t PRA;     /* Parallel port register A */
-    u_int8_t pad1[255];
-    volatile u_int8_t PRB;     /* Parallel port register B */
-    u_int8_t pad2[255];
-    volatile u_int8_t DDRA;    /* Parallel port A data direction register */
-    u_int8_t pad3[255];
-    volatile u_int8_t DDRB;    /* Parallel port B data direction register */
-    u_int8_t pad4[255];
-    volatile u_int8_t TALO;    /* Timer A lower 8 bits */
-    u_int8_t pad5[255];
-    volatile u_int8_t TAHI;    /* Timer A upper 8 bits */
-    u_int8_t pad6[255];
-    volatile u_int8_t TBLO;    /* Timer B lower 8 bits */
-    u_int8_t pad7[255];
-    volatile u_int8_t TBHI;    /* Timer B upper 8 bits */
-    u_int8_t pad8[255];
-    volatile u_int8_t E_LSB;   /* Event counter bits 0-7 */
-    u_int8_t pad9[255];
-    volatile u_int8_t E_MID;   /* Event counter bits 8-15 */
-    u_int8_t pad10[255];
-    volatile u_int8_t E_MSB;   /* Event counter bits 16-23 */
-    u_int8_t pad11[255 + 256];
-    volatile u_int8_t SDR;     /* Serial port data register */
-    u_int8_t pad12[255];
-    volatile u_int8_t ICR;     /* Interrupt control register */
-    u_int8_t pad13[255];
-    volatile u_int8_t CRA;     /* Control register A */
-    u_int8_t pad14[255];
-    volatile u_int8_t CRB;     /* Control register B */
-    u_int8_t pad15[255];
-} CIA;
-
-/* Here are defined common CIA register bits for code clarity */
-#define CIA_ICR_TIMA0  (1 << 0)
-#define CIA_ICR_TIMB0  (1 << 1)
-#define CIA_ICR_TODALRM        (1 << 2)
-#define CIA_ICR_SERDONE        (1 << 3)
-#define CIA_ICR_SIGFLAG        (1 << 4)
-#define CIA_ICR_CIAINT (1 << 7)
-#define CIA_ICR_SETCLR (1 << 7)
-#define CIA_ICR_CLRALL 0x7F
-
-#define CIA_CRA_START  (1 << 0)
-#define CIA_CRA_PBON   (1 << 1)
-#define CIA_CRA_OUTMODE        (1 << 2)
-#define CIA_CRA_RUNMODE        (1 << 3)
-#define CIA_CRA_LOAD   (1 << 4)
-#define CIA_CRA_INMODE (1 << 5)
-#define CIA_CRA_SPMODE (1 << 6)
-
-#define CIA_CRB_START  (1 << 0)
-#define CIA_CRB_PBON   (1 << 1)
-#define CIA_CRB_OUTMODE        (1 << 2)
-#define CIA_CRB_RUNMODE        (1 << 3)
-#define CIA_CRB_LOAD   (1 << 4)
-#define CIA_CRB_INMODE (1 << 5 | 1 << 6)
-#define CIA_CRB_ALARM  (1 << 7)
-
-/* These are Amiga-specific and are different for each of the two CIAs */
-#define CIAA_PRA_MOVL  (1 << 0)        /* Memory overlay bit */
-#define CIAA_PRA_LED   (1 << 1)        /* Pwr LED & aud low pass filt stat */
-#define CIAA_PRA_FCHNG (1 << 2)        /* Floppy disk change */
-#define CIAA_PRA_FRONLY        (1 << 3)        /* Floppy read-only */
-#define CIAA_PRA_FTRK0 (1 << 4)        /* Floppy disk track 0 */
-#define CIAA_PRA_FRDY  (1 << 5)        /* Floppy disk ready for commands */
-#define CIAA_PRA_FIRE0 (1 << 6)        /* Button 1 Port 1 pressed */
-#define CIAA_PRA_FIRE1 (1 << 7)        /* Button 1 port 2 pressed */
-
-#define CIAA_PRB_CDATA 0xFF            /* Centronics data pins/bits */
-
-#define CIAB_PRA_PBUSY (1 << 0)        /* Centronics BUSY */
-#define CIAB_PRA_POUT  (1 << 1)        /* Centronics paper out */
-#define CIAB_PRA_PSEL  (1 << 2)        /* Centronics select */
-#define CIAB_PRA_SDSR  (1 << 3)        /* RS-232 Data Set Ready */
-#define CIAB_PRA_SCTS  (1 << 4)        /* RS-232 Clear To Send */
-#define CIAB_PRA_SDCD  (1 << 5)        /* RS-232 Carrier Detect */
-#define CIAB_PRA_SRTS  (1 << 6)        /* RS-232 Request To Send */
-#define CIAB_PRA_SDTR  (1 << 7)        /* RS-232 Data Terminal Ready */
-
-#define CIAB_PRB_FHSTEP        (1 << 0)        /* Floppy head step */
-#define CIAB_PRB_FHDIR (1 << 1)        /* Floppy head direction */
-#define CIAB_PRB_FSIDE (1 << 2)        /* Floppy side */
-#define CIAB_PRB_FLOP0 (1 << 3)        /* Select Floppy drive 0 */
-#define CIAB_PRB_FLOP1 (1 << 4)        /* Select Floppy drive 1 */
-#define CIAB_PRB_FLOP2 (1 << 5)        /* Select Floppy drive 2 */
-#define CIAB_PRB_FLOP3 (1 << 6)        /* Select Floppy drive 3 */
-#define CIAB_PRB_FMOTOR        (1 << 7)        /* Floppy motor status */
-
-
-/* Useful union to represent 32-bit address split into two 16-bit registers */
-typedef union AADDR {
-    struct {
-       void *addr;             /* Always 32-bit on m68k */
-    } full;
-    struct {
-       u_int16_t addr_h;       /* Bits 16-31 */
-       u_int16_t addr_l;       /* Bits 0-15 */
-    } parial;
-} AADDR;
-
-/* Each of the 4 native 8-bit Amiga channels are controled with this */
-typedef struct AUDCHAN {
-    AADDR AUDLC;       /* Address of audio data */
-    u_int16_t AUDLEN;  /* Length of audio data */
-    u_int16_t AUDPER;  /* Period duration */
-    u_int16_t AUDVOL;  /* Channel volume */
-    u_int16_t AUDDAT;  /* Audio data (to D/A converter) */
-    u_int16_t pad1[2]; /* Unused */
-} AUDCHAN;
-
-/* Sprite information */
-typedef struct SPR {
-    u_int16_t SPRPOS;  /* Sprite start position (vert. and horiz.) */
-    u_int16_t SPRCTL;  /* Control register and vertical stop */
-    u_int16_t SPRDATA; /* Data register A (to RGB output) */
-    u_int16_t SPRDATB; /* Data register B (to RGB output) */
-} SPR;
-
-
-/* And, the Amiga custom chips registers. */
-typedef struct CUST {
-    u_int16_t BLTDDAT; /* Blitter output data (Blitter to RAM) */
-    u_int16_t DMACONR; /* Read DMA control register */
-    u_int16_t VPOSR;   /* MSB of vertical position */
-    u_int16_t VHPOSR;  /* Vertical and horizontal beam position */
-    u_int16_t DSKDATR; /* Dist read data (disk to RAM) */
-    u_int16_t JOY0DAT; /* Joystick/Mouse position game port 0 */
-    u_int16_t JOY1DAT; /* Joystick/Mouse position game port 1 */
-    u_int16_t CLXDAT;  /* Collision register */
-    u_int16_t ADKCONR; /* Read audio/disk control register */
-    u_int16_t POT0DAT; /* Read potentiometer game port 0 */
-    u_int16_t POT1DAT; /* Read potentiometer game port 1 */
-    u_int16_t POTGOR;  /* Read potentiometer port data */
-    u_int16_t SERDATR; /* Read serial port and status */
-    u_int16_t DSKBYTR; /* Read disk data byte and status */
-    u_int16_t INTENAR; /* Read interrupt enable */
-    u_int16_t INTREQR; /* Read interrupt request */
-    AADDR DSKPTR;      /* Disk DMA address */
-    u_int16_t DSKLEN;  /* Disk DMA block length */
-    u_int16_t DSKDAT;  /* Disk write data (RAM to disk) */
-    u_int16_t REFPTR;  /* Refresh counter */
-    u_int16_t VPOSW;   /* Write MSB of vertical beam position */
-    u_int16_t VHPOSW;  /* Write vertical and horizontal beam position */
-    u_int16_t COPCON;  /* Copper control register */
-    u_int16_t SERDAT;  /* Write serial data and stop bits */
-    u_int16_t SERPER;  /* Serial port control register and baud rate */
-    u_int16_t POTGO;   /* Write potentiometer port data and start bit */
-    u_int16_t JOYTEST; /* Write in both mouse counters */
-    u_int16_t STREQU;  /* Horizontal sync with VBlank and equal frame */
-    u_int16_t STRVBL;  /* Horizontal sync wuth vertical blank */
-    u_int16_t STRHOR;  /* Horizontal synchronization signal */
-    u_int16_t STRLONG; /* Long horizontal line marker */
-    /* Following can also be accessed by the copper processor if COPCON=1 */
-    u_int16_t BLTCON0; /* Blitter control register 0 */
-    u_int16_t BLTCON1; /* Blitter control register 1 */
-    u_int16_t BLTAFWM; /* Mask for first data word from A */
-    u_int16_t BLTALWM; /* Mask for last data word from A */
-    AADDR BLTCPTR;     /* Address of source data C */
-    AADDR BLTBPTR;     /* Address of source data B */
-    AADDR BLTAPTR;     /* Address of source data A */
-    AADDR BLTDPTR;     /* Address of destination data D */
-    u_int16_t BLTSIZE; /* Start bit and size of blitter window */
-    u_int16_t BLTCON0L;        /* Like BLTCON0, bits 0-7 */
-    u_int16_t BLTSIZEV;        /* Windth of blitter window */
-    u_int16_t BLTSIZEH;        /* Height of blitter window */
-    u_int16_t BLTCMOD; /* Blitter modulo for source data C */
-    u_int16_t BLTBMOD; /* Blitter modulo for source data B */
-    u_int16_t BLTAMOD; /* Blitter modulo for source data A */
-    u_int16_t BLTDMOD; /* Blitter modulo for destination data D */
-    u_int16_t pad1[4]; /* Unused */
-    u_int16_t BLTCDAT; /* Blitter source data register C */
-    u_int16_t BLTBDAT; /* Blitter source data register B */
-    u_int16_t BLTADAT; /* Blitter source data register A */
-    u_int16_t pad2[3]; /* Unused */
-    u_int16_t DENISEID;        /* Chip identification from Denise */
-    u_int16_t DSKSYNC; /* Disk sync pattern */
-    /* The following registers can always be written to by the Copper */
-    AADDR COP1LPTR;    /* Address of first copper list */
-    AADDR COP2LPTR;    /* Address of second copper list */
-    u_int16_t COPJMP1; /* Jump to start of first copper list */
-    u_int16_t COPJMP2; /* Jump to start of second copper list */
-    u_int16_t COPINS;  /* Copper command register */
-    u_int16_t DIWSTRT; /* Upper left corner of display window */
-    u_int16_t DIWSTOP; /* Lower right corner of display window */
-    u_int16_t DDFSTRT; /* Start of bitplane DMA (horiz. pos.) */
-    u_int16_t DDFSTOP; /* End of bitplane DMA (horiz. pos.) */
-    u_int16_t DMACON;  /* Write DMA control register */
-    u_int16_t CLXCON;  /* Write collision control register */
-    u_int16_t INTENA;  /* Write interrupt enable */
-    u_int16_t INTREQ;  /* Write interrupt request */
-    u_int16_t ADKCON;  /* Audio, disk abd UART control register */
-    AUDCHAN AUDCH[4];  /* Four digital audio channels */
-    AADDR BPLPTR[6];   /* Six bitplane addresses */
-    u_int16_t pad3[4]; /* Unused */
-    u_int16_t BPLCON0; /* Bitplane control register 0 */
-    u_int16_t BPLCON1; /* Bitplane control register 1 (scroll values) */
-    u_int16_t BPLCON2; /* Bitplane control register 2 (priority control) */
-    u_int16_t BPLCON3; /* Bitplane control register 3 */
-    u_int16_t BPL1MOD; /* Bitplane modulo for uneven planes */
-    u_int16_t BPL2MOD; /* Bitplane modulo for even planes */
-    u_int16_t pad4[2]; /* Unused */
-    u_int16_t BPLDAT[6];/* Bitplane data (to RGB output) */
-    u_int16_t pad5[2]; /* Unused */
-    AADDR SPRDATPTR[8];        /* Sprite data registers */
-    SPR SPR[8];                /* Sprite control registers */
-    u_int16_t COLOR[32];/* Color pallete registers (color table) */
-    u_int16_t HTOTAL;  /* Clock count per line (VARBEAM=1) */
-    u_int16_t HSSTOP;  /* H-sync stop position */
-    u_int16_t HBSTRT;  /* H-blank start position */
-    u_int16_t HBSTOP;  /* H-blank stop position */
-    u_int16_t VTOTAL;  /* Number of lines per picture */
-    u_int16_t VSSTOP;  /* V-sync stop line */
-    u_int16_t VBSTRT;  /* V-blank start line */
-    u_int16_t VBSTOP;  /* V-blank stop line */
-    u_int16_t SPRHSTRT;        /* UHRES sprite start line */
-    u_int16_t SPRHSTOP;        /* UHRES sprite stop line */
-    u_int16_t BPLHSTRT;        /* UHRES bitplane start line */
-    u_int16_t BPLHSTOP;        /* UHRES bitplane stop line */
-    u_int16_t HHPOSW;  /* Write DUAL-mode column counter */
-    u_int16_t HHPOSR;  /* Read DUAL-mode column counter */
-    u_int16_t BEAMCON0;        /* Raster beam control register */
-    u_int16_t HSSTRT;  /* H-sync start position */
-    u_int16_t VSSTRT;  /* V-sync start position */
-    u_int16_t HCENTER; /* H-pos. of V-sync in interlace mode */
-    u_int16_t DIWHIGH; /* Screen window, upper bits for start/stop */
-    u_int16_t BPLHMOD; /* UHRES bitplane modulo */
-    AADDR SPRHPTR;     /* UHRES sprite pointer */
-    AADDR BPLHPTR;     /* UHRES bitplane pointer */
-    u_int16_t pad6[7]; /* Unused */
-} CUST;
-
-/* And again some bits definitions for code clarity */
-#define DMACON_AUDIO0  (1 << 0)
-#define DMACON_AUDIO1  (1 << 1)
-#define DMACON_AUDIO2  (1 << 2)
-#define DMACON_AUDIO3  (1 << 3)
-#define DMACON_AUDIO   (1 << 0 | 1 << 1 | 1 << 2 | 1 << 3)
-#define DMACON_FLOPPY  (1 << 4)
-#define DMACON_SPRITE  (1 << 5)
-#define DMACON_BLITTER (1 << 6)
-#define DMACON_COPPER  (1 << 7)
-#define DMACON_BITPLANE        (1 << 8)
-#define DMACON_MASTER  (1 << 9)
-#define DMACON_PRIORITY        (1 << 10)
-#define DMACON_ZEROS   (1 << 13)
-#define DMACON_BLITTING        (1 << 14)
-#define DMACON_SETCLR  (1 << 15)
-#define DMACON_CLRALL  0x07FF
-
-#define ADKCON_0MODVOL1        (1 << 0)
-#define ADKCON_1MODVOL2        (1 << 1)
-#define ADKCON_2MODVOL3        (1 << 2)
-#define ADKCON_3OFF    (1 << 3)
-#define ADKCON_0MODPER1        (1 << 4)
-#define ADKCON_1MODPER2        (1 << 5)
-#define ADKCON_2MODPER3 (1 << 6)
-#define ADKCON_3OFF2   (1 << 7)
-#define ADKCON_FLOP_GCR        (1 << 8)
-#define ADKCON_GCR_SYNC        (1 << 9)
-#define ADKCON_SYNC    (1 << 10)
-#define ADKCON_UARTBRK (1 << 11)
-#define ADKCON_FLOP_MFM        (1 << 12)
-#define ADKCON_SETCLR  (1 << 15)
-
-/* Most of these are shared by INTREQ, INTREQR, INTENA, INTENAR */
-#define INT_SERTBE     (1 << 0)
-#define INT_FLOPBLCK   (1 << 1)
-#define INT_SOFT       (1 << 2)
-#define INT_CIAA       (1 << 3)
-#define INT_COPPER     (1 << 4)
-#define INT_VBLANK     (1 << 5)
-#define INT_BLITRDY    (1 << 6)
-#define INT_AUDIO0     (1 << 7)
-#define INT_AUDIO1     (1 << 8)
-#define INT_AUDIO2     (1 << 9)
-#define INT_AUDIO3     (1 << 10)
-#define INT_AUDIO      (1 << 7 | 1 << 8 | 1 << 9 | 1 << 10)
-#define INT_SERRBF     (1 << 11)
-#define INT_FLOPSYNC   (1 << 12)
-#define INT_CIAB       (1 << 13)
-#define INT_LEVEL6     (1 << 14)       /* INTREQR */
-#define INT_MASTER     (1 << 14)       /* INTENA */
-#define INT_SETCLR     (1 << 15)       /* INTENA & INTREQ */
-#define INTENA_CLRALL  0x3FFF
-#define INTREQ_CLRALL  0x7FFF
-
-
-
-
-/* Stuff we need to initialize before calling Xisop's main() */
-
-/*
-#define        MEMF_CHIP       0x0001
-#define MEMF_FAST      0x0002
-
-void *OpenLibrary(char *, long);
-void CloseLibrary(void *);
-long AvailMem(long);
-void *AllocMem(long, long);
-void *AllocAbs(long, void *);
-void FreeMem(void *, long);
-void Permit(void);
-void Enable(void);
-void *SuperState(void);
-void UserState(void *);
-
-void jdelay(u_int32_t);
-u_int32_t atime(void);
-*/
-void ldelay(u_int32_t);
-
-void Alert(long, void *);
-void Forbid(void);
-void Disable(void);
-void _supervisor(u_int32_t *, size_t, void (*)(void));
-
-/* Set priority level */
-u_int16_t asplvblank(void);
-u_int16_t asplsched(void);
-/* Set priority level exit */
-void asplx(u_int16_t);
-
-
-
-/* Things we export for Xisop
- * --------------------------
- */
-
-
-/* Memory management */
-
-/* Our preferred page size. As Xisop does not support MMU, any size which is
- * resonable and a multiple of 16 can be used.
- */
-#define _PAGE_SIZE     4096
-
-/* Definitions we need for mpool_t */
-#define _MPOOLS                7
-#define _MPOOLSTART    16
-#define _MPOOLSTEP     1
-
-/* Memory types we setup */
-enum _memtypes {
-       _MEM_FAST = 0,
-       _MEM_CHIP,
-       _MEM_MAX
-};
-
-/* Scheduler timer rate */
-#define SCHEDTIMER_HZ  200     /* 4 times the vertical blank rate for now */
-
-/* Interrupt facilities we provide */
-enum _facilities {
-    _FACILITY_SCHEDTIMER = 0,
-    _FACILITY_VBLANK,
-    _FACILITY_FLOPPYSYNC,
-    _FACILITY_FLOPPYBLOCK,
-    _FACILITY_SERIALRBF,
-    _FACILITY_SERIALTBE,
-    _FACILITY_AUDIO,
-    _FACILITY_BLITTERREADY,
-    _FACILITY_COPPER,
-    _FACILITY_CIATIMB0,
-    _FACILITY_KEYBOARD,
-    _FACILITY_TRAP,
-    _FACILITY_MAX
-};
-
-
-/* Functions we provide */
-void _init_exceptions(void);
-void _syscall(u_int32_t, void *, void *);
-void _yield(void *);
-void _port_init(void);
-void _panic(u_int16_t);        /* XXX */
-
-
-
-#endif
diff --git a/Xisop/src/ports/amiga/support_c.c b/Xisop/src/ports/amiga/support_c.c
deleted file mode 100644 (file)
index 71aee29..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/* $Id: support_c.c,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <common/types.h>
-#include "support.h"
-
-
-
-/* These functions are similar to the _spl()/_splx() and spl()/splx() ones
- * although they work directly with the Amiga hardware INTENA register,
- * thus only disabling the specified interrupt (rather than setting a level).
- * XXX Problem with this is that it's absolutely architecture-dependant.
- * The general purpose spl() functions should be common to the various hardware
- * Xisop supports. Hmm but the devices will be architecture dependant as well;
- * unless kernel provides some basics to access some common things like
- * RS-232 and console I/O.
- */
-
-u_int16_t asplvblank(void)
-{
-    u_int16_t old;
-
-    old = CUSTOM->INTENAR;
-    CUSTOM->INTENA = INT_VBLANK;
-
-    return old;
-}
-
-/* Note: also prevents other CIA-B interrupts meanwhile */
-u_int16_t asplsched(void)
-{
-    u_int16_t old;
-
-    old = CUSTOM->INTENAR;
-    CUSTOM->INTENA = INT_CIAB;
-
-    return old;
-}
-
-void asplx(u_int16_t old)
-{
-    CUSTOM->INTENA = old | INT_SETCLR;
-}
diff --git a/Xisop/src/ports/amiga/support_s.s b/Xisop/src/ports/amiga/support_s.s
deleted file mode 100644 (file)
index 4f54c6e..0000000
+++ /dev/null
@@ -1,865 +0,0 @@
-/* $Id: support_s.s,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include "support.h"
-
-
-| exec.library base
-ExecBase =     0x0004
-| Various Amiga custom chips registers
-VPOSR  =       0x00DFF004
-VHPOSR =       0x00DFF006
-TODHI  =       0x00BFEA01
-TODMID =       0x00BFE901
-TODLO  =       0x00BFE801
-INTREQR        =       0x00DFF01E
-INTREQ =       0x00DFF09C
-INTENAR        =       0x00DFF01C
-INTENA =       0x00DFF09A
-COLOR0 =       0x00DFF180
-CIA_ICR        =       0x00BFDD00
-
-
-.globl Alert, Forbid, Disable, AvailMem, AllocMem, AllocAbs, FreeMem
-.globl _supervisor, _init_exceptions, _syscall, _yield
-.globl jdelay, ldelay, atime
-
-.text
-
-
-| AmigaOS minimal library. We include here the various functions which the
-| kernel initialization may need.
-
-
-| void [-108]Alert([d7]long alertNum,[a5]char *flags)
-|
-Alert:
-       moveml  %d7/%a5-%a6, %sp@-
-       moveal  ExecBase:w, %a6
-       movel   %sp@(16), %d7
-       moveal  %sp@(20), %a5
-       jsr     %a6@(-108)
-       moveml  %sp@+, %a6-%a5/%d7
-       rts
-
-
-| void [-132]Forbid(void)
-|
-Forbid:
-       movel   %a6, %sp@-
-       moveal  ExecBase:w, %a6
-       jsr     %a6@(-132)
-       moveal  %sp@+, %a6
-       rts
-
-
-/*
-| void [-120]Disable(void)
-|
-Disable:
-       movel   %a6, %sp@-
-       moveal  ExecBase:w, %a6
-       jsr     %a6@(-120)
-       moveal  %sp@+, %a6
-       rts
-
-
-| [d0]long = [-216]Availmem([d1]long reqs)
-|
-AvailMem:
-       moveml  %a6/%d1, %sp@-
-       moveal  ExecBase:w, %a6
-       movel   %sp@(12), %d1
-       jsr     %a6@(-216)
-       moveml  %sp@+, %d1/%a6
-       rts
-
-
-| [d0]void * = [-198]AllocMem([d0]long bytes, [d1]long reqs)
-|
-AllocMem:
-       moveml  %a6/%d0-%d1, %sp@-
-       moveal  ExecBase:w, %a6
-       movel   %sp@(16), %d0
-       movel   %sp@(20), %d1
-       jsr     %a6@(-198)
-       moveal  %d0, %a0
-       moveml  %sp@+, %d1-%d0/%a6
-       rts
-
-
-| [d0]void * = [-204]AllocAbs([d0]long bytes, [a1]void *addr)
-|
-AllocAbs:
-       moveml  %a1/%a6/%d0, %sp@-
-       moveal  ExecBase:w, %a6
-       movel   %sp@(16), %d0
-       moveal  %sp@(20), %a1
-       jsr     %a6@(-204)
-       moveal  %d0, %a0
-       moveml  %sp@+, %d0/%a6/%a1
-       rts
-
-
-| void [-210]FreeMem([a1]memptr, [d0]bytesize)
-|
-FreeMem:
-       moveml  %a1/%a6/%d0, %sp@-
-       moveal  ExecBase:w, %a6
-       moveal  %sp@(16), %a1
-       movel   %sp@(20), %d0
-       jsr     %a6@(-210)
-       moveml  %sp@+, %d0/%a6/%a1
-       rts
-*/
-
-
-| void _supervisor(u_int32_t *sp, size_t sz, void (*func)(void))
-| Allows to gain m68k supervisor access, and sets up the supervisor stack
-| pointer to the specified address. The supplied entry point function is
-| then called. It is expected to never return, we thus don't need to worry
-| about the registers we modify, except for A7/SSP.
-|
-_supervisor:
-       moveal  %sp@(4), %a1    | SSP to set
-       movel   %sp@(8), %d1    | Size to add
-       moveal  %sp@(12), %a2   | Function to call
-       moveal  ExecBase:w, %a6
-       jsr     %a6@(-150)      | AmigaOS SuperState() exec.library call
-       moveal  %a1, %a7        | Set SSP
-       addal   %d1, %a7        | Jump to end of stack buffer
-       jsr     %a2@            | Call famous function
-       rts                     | Should never be reached.
-
-
-| void _init_exceptions(void)
-| Called from C to initialize interrupts, traps and exception vectors
-|
-_init_exceptions:
-       clrl    _interrupt_depth
-       bsrw    trap_init
-       bsrw    int_init
-       bsrw    except_init
-       rts
-
-
-| Other Amiga-specific assembler routines. The following deal with exceptions,
-| traps and interrupts.
-
-
-| void trap_init(void)
-| Setup our 15 trap vectors
-|
-trap_init:
-       moveml  %a0/%a1, %sp@-
-       moveal  #0x80, %a0
-       lea     %pc@(trap_catch0), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch1), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch2), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch3), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch4), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch5), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch6), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch7), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch8), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch9), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch10), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch11), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch12), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch13), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(trap_catch14), %a1
-       movel   %a1, %a0@
-       moveml  %sp@+, %a1/%a0
-       rts
-
-
-| And our trap handlers
-
-| This trap is special as it handles the backend for the _syscall() function
-| which prototype is as follows:
-| void _syscall(u_int32_t code, void *res, void *args)
-| _syscall() just puts the arguments onto d0, a0 and a1 registers, and causes
-| a trap 0. Our purpose is to copy those arguments on the supervisor
-| stack, call _scatch(), free our arguments from the supervisor stack and
-| return from the exception. The _syscall() caller will free it's own arguments
-| from the user stack.
-|
-trap_catch0:
-       addql   #1, _interrupt_depth
-
-       | Backup registers on supervisor stack
-       | _syscall backed up d0 and a0-a1 as it modifies them to store the
-       | registers for us.
-       |
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-
-       | Move registers which _syscall() setup for us into the stack and
-       | call void _scatch(u_int32_t, void *, void *).
-       |
-       movel   %a1, %sp@-
-       movel   %a0, %sp@-
-       movel   %d0, %sp@-
-       bsrl    _scatch
-       lea     %sp@(12), %sp   | faster than addl #12, %sp
-
-       | Restore registers we backed up
-       |
-       moveml  %sp@+, %a6-%a0/%d7-%d0
-       subql   #1, _interrupt_depth
-       rte
-
-
-| This trap is also special in that it triggers an immediate context switch.
-| Used to implement _yield(). It is implemented very similarly to the scheduler
-| timer interrupt handler which forces task preemption.
-|
-trap_catch1:
-       addql   #1, _interrupt_depth
-
-       | First save SR and change it so that we be uninterruptible
-       |
-       movew   %sr, %sp@-
-       movew   #0x2700, %sr
-
-       | Save current CPU context to root->curctx
-       |
-       movel   %a0, %sp@-              | Save A0 internally as we need it
-       movel   %usp, %a0
-       movel   %a0, %sp@-              | And USP
-       lea     root, %a0               | Load root->curctx _ctx_t *
-       moveal  %a0@(44), %a0
-       lea     %a0@(70), %a0           | Position now after struct's SR
-
-       | Save SR, predecrementing. Normally stored at %sp@, but we saved
-       | 10 bytes in the stack, and are using %sp@(10).
-       movew   %sp@(10), %a0@-
-       | Save PC from SS, which is normally stored at %sp@(2), but we saved
-       | 10 bytes in the stack, so are using %sp@(12).
-       movel   %sp@(12), %a0@-         | Save PC, from SS
-       moveml  %a1-%a6/%d0-%d7, %a0@-  | Save A6-A1, D7-D0
-       movel   %sp@+, %a0@-            | Save USP/A7 from backup
-       movel   %sp@+, %a0@-            | Save A0 from backup
-
-       | Now call schedule(), passing the supplied argument we were passed
-       |
-       movel   _yieldparam, %sp@-
-       bsrl    schedule
-       addql   #4, %sp
-
-       | Load context from root->curctx, which may have changed
-       |
-       lea     root, %a0               | Load root->curctx _ctx_t *
-       moveal  %a0@(44), %a0
-       addql   #4, %a0                 | Skip A0 for now as we use it
-       movel   %a0@+, %a1
-       movel   %a1, %usp               | Restore USP/A7
-       moveml  %a0@+, %d7-%d0/%a6-%a1  | Restore D0-D7, A1-A6
-       | Load PC from context and save in SP. Normally it would be %sp@(2)
-       | but there remains 2 bytes we saved in the stack and are using %sp@(4)
-       movel   %a0@+, %sp@(4)          | PC
-       | Restore SR, making sure that supervisor mode bit is set. Normally
-       | stored at %sp@, but we saved 2 bytes on the stack, so %sp@(2).
-       movew   %a0@, %sp@(2)
-       moveal  %a0@(-68), %a0          | Restore A0
-
-       | Restore normal SR
-       |
-       movew   %sp@+, %sr
-
-       | Return from exception, but to PC we loaded
-       |
-       subql   #1, _interrupt_depth
-       rte
-
-
-| These trap handlers consist of a backend for the C _tcatch() function.
-|
-trap_catch2:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     0
-       braw    1f
-trap_catch3:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     1
-       braw    1f
-trap_catch4:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     2
-       braw    1f
-trap_catch5:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     3
-       braw    1f
-trap_catch6:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     4
-       braw    1f
-trap_catch7:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     5
-       braw    1f
-trap_catch8:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     6
-       braw    1f
-trap_catch9:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     7
-       braw    1f
-trap_catch10:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     8
-       braw    1f
-trap_catch11:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     9
-       braw    1f
-trap_catch12:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     10
-       braw    1f
-trap_catch13:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     11
-       braw    1f
-trap_catch14:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     12
-1:
-       | Call our C function: void _tcatch(int);
-       |
-       bsrl    _tcatch
-       addql   #4, %sp
-       moveml  %sp@+, %a6-%a0/%d7-%d0
-       subql   #1, _interrupt_depth
-       rte
-
-
-
-| C frontend to catch interrupts. Because of the way Amiga works with INTREQ
-| it is important that they verify and reset their cause bits. This is easily
-| done when dispatching all interrupt levels to a main single C function, with
-| the interrupt level passed as an argument, and leave it do all the work.
-| This is what was previously done here. However, leaving the C function do
-| all the work implied wasting some CPU cycles. For instance, the level is
-| already known via the handler being called, when we still let the C code
-| perform that condition checking again. Moreover, INTREQ handling wasn't
-| particularly optimized properly (using GCC 2.95.3 with m68k output).
-| As some interrupt levels may be generated very frequently it is best to
-| optimize this as much as possible.
-| So we separated the handlers and let the assembler frontend handle INTREQ.
-| For most interrupt handlers, We call a C function handler per interrupt
-| level:
-|    void _icatch<n>(u_int16_t intreqmask)
-| where <intreqmask> is obtained from INTREQR, and we make sure to reset
-| the bits of the mask in INTREQ. It would also be possible to add some more
-| assembly here if wanted to serve special interrupts faster, like RS-232 I/O.
-| NOTE: GCC requires a 32-bit stack entry even for a 16-bit argument.
-
-
-| void int_init(void)
-| Setup our 6 interrupt vectors. Amiga does not use m68k interrupt level 7
-| and they are non-maskable (and hence are of no use to us anyways).
-|
-int_init:
-       moveml  %a0-%a1, %sp@-
-       moveal  #0x64, %a0
-       lea     %pc@(int_catch1), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(int_catch2), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(int_catch3), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(int_catch4), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(int_catch5), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(int_catch6), %a1
-       movel   %a1, %a0@
-       moveml  %sp@+, %a1-%a0
-       rts
-
-
-| These handlers call the various C _icatch<n>() functions
-int_catch1:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       movew   INTREQR, %sp@-
-       clrw    %sp@-
-       bsrl    _icatch1
-       addql   #4, %sp
-       movew   #0x0007, INTREQ
-       moveml  %sp@+, %a6-%a0/%d7-%d0
-       subql   #1, _interrupt_depth
-       rte
-int_catch2:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       movew   INTREQR, %sp@-
-       clrw    %sp@-
-       bsrl    _icatch2
-       addql   #4, %sp
-       movew   #0x0008, INTREQ
-       moveml  %sp@+, %a6-%a0/%d7-%d0
-       subql   #1, _interrupt_depth
-       rte
-int_catch3:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       movew   INTREQR, %sp@-
-       clrw    %sp@-
-       bsrl    _icatch3
-       addql   #4, %sp
-       movew   #0x0070, INTREQ
-       moveml  %sp@+, %a6-%a0/%d7-%d0
-       subql   #1, _interrupt_depth
-       rte
-int_catch4:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       movew   INTREQR, %sp@-
-       clrw    %sp@-
-       bsrl    _icatch4
-       addql   #4, %sp
-       movew   #0x0780, INTREQ
-       moveml  %sp@+, %a6-%a0/%d7-%d0
-       subql   #1, _interrupt_depth
-       rte
-int_catch5:
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       movew   INTREQR, %sp@-
-       clrw    %sp@-
-       bsrl    _icatch5
-       addql   #4, %sp
-       movew   #0x1800, INTREQ
-       moveml  %sp@+, %a6-%a0/%d7-%d0
-       subql   #1, _interrupt_depth
-       rte
-
-
-| This interrupt handler is special as it also comports CIAB timer A interrupt,
-| which is used by Xisop for the preeptive scheduler. We thus handle it
-| especially, entirely in assembly.
-| Unlike for other interrupt levels, we not just simply save and restore all
-| registers. We store the current context into root->curctx, call schedule(),
-| then load the context from root->curctx.
-| This executes on the Supervisor Stack, and the User Stack Pointer as such
-| is not modified except in context switches.
-|
-int_catch6:
-       addql   #1, _interrupt_depth
-
-       | Raise level to 7
-       |
-       movew   %sr, %sp@-
-       movew   #0x2700, %sr
-
-       | Save D0 as we need it
-       |
-       movel   %d0, %sp@-
-
-       | if (!(intreq & INT_CIAB)) goto 1
-       |
-       movew   INTREQR, %d0
-       btst    #13, %d0
-       beqs    1f
-
-       | if (icrmask & CIA_ICR_TIMA0) goto 2
-       |
-       moveb   CIA_ICR, %d0
-       btst    #0, %d0
-       bnes    2f
-1:
-       | Not the CIAB Timer A interrupt, Restore D0 and end
-       |
-       movel   %sp@+, %d0
-       braw    4f
-2:
-       | Restore D0 and continue
-       |
-       movel   %sp@+, %d0
-
-       | Tasks are expected to not run in supervisor mode.
-        | We have syscalls (including sys_call() one allowing to execute
-       | arbitrary code in supervisor mode), and public interrupt facilities
-       | (to which they can attach hooks) for them which should suffice.
-       | Moreover, system calls are uninterruptible by the scheduler when
-       | running.
-
-       | Store current user context into root->curctx buffer
-       |
-       movel   %a0, %sp@-              | Save A0 internally as we need it
-       movel   %usp, %a0
-       movel   %a0, %sp@-              | And USP
-       lea     root, %a0               | Load root->curctx _ctx_t *
-       moveal  %a0@(44), %a0
-       lea     %a0@(70), %a0           | Position now after struct's SR
-       | Save SR, predecrementing. Normally stored at %sp@, but we saved
-       | 10 bytes in the stack, and are using %sp@(10).
-       movew   %sp@(10), %a0@-
-       | Save PC from SS, which is normally stored at %sp@(2), but we saved
-       | 10 bytes in the stack, so are using %sp@(12).
-       movel   %sp@(12), %a0@-         | Save PC, from SS
-       moveml  %a1-%a6/%d0-%d7, %a0@-  | Save A6-A1, D7-D0
-       movel   %sp@+, %a0@-            | Save USP/A7 from backup
-       movel   %sp@+, %a0@-            | Save A0 from backup
-
-       | Execute _FACILITY_SCHEDTIMER hooks
-       |
-       clrl    %sp@-
-       pea     0                       | _FACILITY_SCHEDTIMER
-       bsrl    facility_exechooks
-       addql   #8, %sp
-
-       | The following ensures to only perform a context switch if not
-       | currently executing a system call trap or other interrupt. The
-       | reason we need this is that the scheduler interrupt has a very
-       | high priority (6), which can actually interrupt most other
-       | exception handlers.
-       |
-       | if (_interrupt_depth != 1) goto 3
-       |
-       cmpil   #1, _interrupt_depth
-       bnes    3f
-
-       | Call schedule(), which internally handles scheduling, and can
-       | modify root->curctx and root->curtask
-       |
-       pea     0
-       bsrl    schedule
-       addql   #4, %sp
-
-3:
-       | Load back root->curctx into the current user CPU context
-       |
-       lea     root, %a0               | Load root->curctx _ctx_t *
-       moveal  %a0@(44), %a0
-       addql   #4, %a0                 | Skip A0 for now as we use it
-       movel   %a0@+, %a1
-       movel   %a1, %usp               | Restore USP/A7
-       moveml  %a0@+, %d7-%d0/%a6-%a1  | Restore D0-D7, A1-A6
-       | Load PC from context and save in SP. Normally it would be %sp@(2)
-       | but there remains 2 bytes we saved in the stack and are using %sp@(4)
-       movel   %a0@+, %sp@(4)          | PC
-       | Restore SR, making sure that supervisor mode bit is set. Normally
-       | stored at %sp@, but we saved 2 bytes on the stack, so %sp@(2).
-       movew   %a0@, %sp@(2)
-       moveal  %a0@(-68), %a0          | Restore A0
-
-4:
-       | Exit point
-       |
-       | Reset INTREQ like for other levels interrupt handlers
-       |
-       movew   #0x2000, INTREQ
-
-       | Restore Interrupt Priority Level
-       |
-       movew   %sp@+, %sr
-
-       | Return using the %sp@(2) address from SS
-       |
-       subql   #1, _interrupt_depth
-       rte
-
-
-
-| void except_init(void)
-| Setup special exception handlers.
-|
-except_init:
-       moveml  %a0-%a1, %sp@-
-       moveal  #0x8, %a0
-       lea     %pc@(except_catch1), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(except_catch2), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(except_catch3), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(except_catch4), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(except_catch5), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(except_catch6), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(except_catch7), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(except_catch8), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(except_catch9), %a1
-       movel   %a1, %a0@+
-       lea     %pc@(except_catch10), %a1
-       movel   %a1, %a0@
-       moveal  #0x3c, %a0
-       lea     %pc@(except_catch11), %a1
-       movel   %a1, %a0@
-       moveal  #0x60, %a0
-       lea     %pc@(except_catch12), %a1
-       movel   %a1, %a0@
-       moveal  #0x7c, %a0
-       lea     %pc@(except_catch13), %a1
-       movel   %a1, %a0@
-       moveml  %sp@+, %a1-%a0
-       rts
-
-
-| Our exception handlers. Internally calling _ecatch() C function.
-|
-except_catch1: | Bus error
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     1
-       braw    1f
-except_catch2: | Address error
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     2
-       braw    1f
-except_catch3: | Illegal operation
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     3
-       braw    1f
-except_catch4: | Division by zero
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     4
-       braw    1f
-except_catch5: | CHK
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     5
-       braw    1f
-except_catch6: | TRAPV
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     6
-       braw    1f
-except_catch7: | Privilege violation
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     7
-       braw    1f
-except_catch8: | Trace
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     8
-       braw    1f
-except_catch9: | Line A Emu
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     9
-       braw    1f
-except_catch10:        | Line F Emu
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     10
-       braw    1f
-except_catch11:        | Uninitialized interrupt vector
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     11
-       braw    1f
-except_catch12:        | Unjustified interrupt vector
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     12
-       braw    1f
-except_catch13: | NMI ?
-       addql   #1, _interrupt_depth
-       moveml  %d0-%d7/%a0-%a6, %sp@-
-       pea     13
-1:
-       | Call our C function: void _ecatch(int);
-       bsrl    _ecatch
-       addql   #4, %sp
-       moveml  %sp@+, %a6-%a0/%d7-%d0
-       subql   #1, _interrupt_depth
-       rte
-
-
-
-| void _syscall(int function, void *res, void *args)
-| C interface to Xisop syscalls. Because of the C prototype, the three
-| arguments are already pushed unto the user stack before calling _syscall().
-| We thus place them into registers d0, a0 and a1, and cause a trap 0,
-| which resumes execution at trap_catch0 in supervisor mode.
-|
-_syscall:
-       | Save registers we modify
-       moveml  %d0/%a0-%a1, %sp@-
-
-       | Prepare arguments
-       movel   %sp@(16), %d0
-       moveal  %sp@(20), %a0
-       moveal  %sp@(24), %a1
-       | Poof! Through the gate
-       trap    #0
-
-       | Restore registers
-       moveml  %sp@+, %a1-%a0/%d0
-       rts
-
-
-| void _yield(task_t *)
-| Allows a task to immediately return control to the scheduler, allowing
-| other tasks some CPU time immediately. The optional task_t pointer argument
-| permits to suggest a task to run soon again to the scheduler, and should
-| consist of another STATE_READY task.
-| We use a special static buffer to hold this value because we do not want
-| to taint the registers before the context gets saved. Moreover, if we tried
-| to save and restore registers from the stack, we probably would be stealing
-| bytes from the stack of another task which probably was preempted rather than
-| interrupted using _yield() the last time.
-| I tried pushing the argument on the stack and having the other side check
-| it in via the User Stack Pointer, but it failed for some reason.
-|
-_yield:
-       | Use a static buffer since we're not supposed to modify any registers
-       | and that we can't save them on the stack since at return we won't
-       | have the same stack, obviously.
-       movel   %sp@(4), _yieldparam
-       trap    #1
-       rts
-
-
-
-| These consist of various delay functions. These are not particularly
-| useful in multitasking environments since they hug the CPU in loops,
-| but are great for testing purposes.
-
-
-/*
-| void jdelay(long jiffies)
-| Waits until completion of the current frame (vblank), 1/60th of a second
-| for NTSC and 1/50th for PAL, by checking current hardware raster position.
-| Not ideal as using an interrupt, but works. j stands for jiffy, a frame.
-|
-jdelay:
-       moveml  %d0-%d1, %sp@-
-       movel   %sp@(12), %d0
-1:
-       movel   VPOSR, %d1              | Read both VPOSR and VHPOSR at once
-       andil   #0x0001FF00, %d1        | Mask out the vertical beam position
-       bnes    1b
-       dbf     %d0, 1b
-       moveml  %sp@+, %d1-%d0
-       rts
-*/
-
-
-| void ldelay(long lines)
-| Similar to the above function but waits approximately for the start of the
-| next video raster line.
-|
-ldelay:
-       moveml  %d0-%d1, %sp@-
-       movel   %sp@(12), %d0
-1:     movew   VHPOSR, %d1
-       andiw   #0x000F, %d1
-       bnes    1b
-       dbf     %d0, 1b
-       moveml  %sp@+, %d1-%d0
-       rts
-
-
-*/
-| Time related functions.
-
-
-| u_int32_t atime(void)
-| Obtains current time in 50/60Hz resolution, from CIA-A TOD counter
-|
-atime:
-       clrl    %d0
-       moveb   TODHI, %d0
-       lsll    #4, %d0
-       lsll    #4, %d0
-       moveb   TODMID, %d0
-       lsll    #4, %d0
-       lsll    #4, %d0
-       moveb   TODLO, %d0
-       rts
-*/
-
-
-.data
-.align 4
-
-| This counter is used to count the depth of interrupts, so that the scheduler
-| interrupt, which runs at a very high priority, only switches state if the
-| depth is 1. All interrupt and trap handlers increase this variable at
-| startup and decrease it at exit.
-|
-_interrupt_depth:
-       .long   0
-
-| This consists of the parameter which is passed to _yield(), because we cannot
-| save registers on the stack and expect the same values to be loaded back
-| after causing trap #1, because obviously the context (and SP) may have
-| changed.
-|
-_yieldparam:
-       .long   0
diff --git a/Xisop/src/processors/i386/make.sh b/Xisop/src/processors/i386/make.sh
deleted file mode 100755 (executable)
index 0772960..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-# $Id: make.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ../../makedefs.sh
-
-show $C_COMPS -I$SRCDIR support.s
-show $C_COMPS udivsi3.s
-show $C_COMPS mulsi3.s
-show $C_AR ar/support.a support.o udivsi3.o mulsi3.o
-show $C_RANLIB ar/support.a
diff --git a/Xisop/src/processors/i386/support.h b/Xisop/src/processors/i386/support.h
deleted file mode 100644 (file)
index 380c7ea..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* $Id: support.h,v 1.3 2004/01/30 07:01:24 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef PROCESSOR_I386_H
-#define PROCESSOR_I386_H
-
-
-
-#include <common/types.h>
-
-
-
-#define _LITTLE_ENDIAN
-
-typedef struct _ctx {
-    void *esp, *ebp, *eip;             /* eip == PC, esp = stack top */
-    u_int32_t eax, ebx, ecx, edx;
-    u_int32_t esi, edi;
-    u_int32_t eflags;
-    u_int32_t es, fs, gs, ds;
-} volatile _ctx_t;
-
-typedef volatile int32_t       _lock_t;
-typedef int32_t                        _rlock_t;
-
-
-
-void _lock_init(_lock_t *);
-void _lock_acquire(_lock_t *);
-void _lock_release(_lock_t *);
-bool _lock_try(_lock_t *);
-bool _lock_available(_lock_t *);
-
-void _rlock_init(_rlock_t *);
-void _rlock_acquire(_rlock_t *);
-void _rlock_release(_rlock_t *);
-bool _rlock_try(_rlock_t *);
-bool _rlock_available(_rlock_t *);
-
-u_int16_t _bswap16(u_int16_t);
-u_int32_t _bswap32(u_int32_t);
-
-void _ctx_init(_ctx_t *, u_int32_t *, size_t, void *);
-
-void _idle(void);
-
-
-
-#endif
diff --git a/Xisop/src/processors/i386/support.s b/Xisop/src/processors/i386/support.s
deleted file mode 100644 (file)
index 34b4564..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/* $Id: support.s,v 1.4 2004/01/30 07:29:14 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-.globl _spl, _splx
-.globl _lock_init, _lock_acquire, _lock_try, _lock_available, _lock_release
-.globl _rlock_init, _rlock_acquire, _rlock_try, _rlock_release, _rlock_available
-.globl _ctx_init
-.globl setjmp, longjmp
-.globl _idle
-.globl _bswap16, _bswap32
-
-.text
-
-
-/* _spl_t _spl(_spl_t) _spl_t = ?XXX?
-*/
-_spl:
-/*XXX*/
-       ret
-
-
-_lock_init:
-       mov     0x4(%esp,1), %eax
-       movl    $0x0, (%eax)
-       ret
-
-_lock_acquire:
-       mov     0x4(%esp,1), %edx
-       mov     $0x1, %eax
-       lea     0x0(%esi), %esi
-1:     xchg    %eax, (%edx)
-       test    %eax, %eax
-       jne     1b
-       ret
-
-_lock_release:
-       mov     0x4(%esp,1), %eax
-       movl    $0x0, (%eax)
-       ret
-
-_lock_try:
-       mov     0x4(%esp,1), %edx
-       mov     $0x1, %eax
-       xchg    %eax, (%edx)
-       test    %eax, %eax
-       je      1f
-       xor     %eax, %eax
-       ret
-1:     mov     $0x1, %eax
-       ret
-
-_lock_available:
-       mov     0x4(%esp,1), %eax
-       cmpl    $0x0, (%eax)
-       je      1f
-       xor     %eax, %eax
-       ret
-1:     mov     $0x1, %eax
-       ret
-
-
-_rlock_init:
-       mov     0x4(%esp,1), %eax
-       movl    $0x0, (%eax)
-       ret
-
-_rlock_acquire:
-       mov     0x4(%esp,1), %eax
-       incl    (%eax)
-       ret
-
-_rlock_release:
-       mov     0x4(%esp,1), %eax
-       decl    (%eax)
-       ret
-
-_rlock_try:
-       mov     0x4(%esp,1), %eax
-       incl    (%eax)
-       cmpl    $0x1, (%eax)
-       je      1f
-       decl    (%eax)
-       xor     %eax, %eax
-       ret
-1:     mov     $0x1, %eax
-       ret
-
-_rlock_available:
-       mov     0x4(%esp,1), %eax
-       cmpl    $0x0, (%eax)
-       je      1f
-       xor     %eax, %eax
-       ret
-1:     mov     $0x1, %eax
-       ret
-
-
-_bswap16:
-       mov     0x4(%esp,1), %eax
-       ror     $0x8, %ax
-       ret
-
-_bswap32:
-       mov     0x4(%esp,1), %eax
-       ror     $0x8, %ax
-       ror     $0x10, %eax
-       ror     $0x8, %ax
-       ret
-
diff --git a/Xisop/src/processors/m68k/clean.sh b/Xisop/src/processors/m68k/clean.sh
deleted file mode 100755 (executable)
index 63982c8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-# $Id: clean.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ../../generic_makedefs.sh
-
-cleanlib math
-show $L_RM support.o ar/support.a
diff --git a/Xisop/src/processors/m68k/make.sh b/Xisop/src/processors/m68k/make.sh
deleted file mode 100755 (executable)
index 20a99e2..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-# $Id: make.sh,v 1.1 2003/10/26 21:19:57 mmondor Exp $
-
-. ../../makedefs.sh
-
-show $C_COMPS -I$SRCDIR support.s
-buildlib math
-show $C_AR ar/support.a support.o math/*.o
-show $C_RANLIB ar/support.a
diff --git a/Xisop/src/processors/m68k/math/README b/Xisop/src/processors/m68k/math/README
deleted file mode 100644 (file)
index 74461b6..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-Some math functions are required by GCC m68k compiled code. Those were obtained
-from the NetBSD kernel m68k library and adapted. Their BSD license file headers
-were unchanged, however.
diff --git a/Xisop/src/processors/m68k/math/divsi3.s b/Xisop/src/processors/m68k/math/divsi3.s
deleted file mode 100644 (file)
index 8c8aa40..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* $Id: divsi3.s,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Matthew Fredette.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-.globl __divsi3
-
-
-
-| NB: this requires that __udivsi3 preserve %a0:
-__divsi3:
-       movel   %sp@(4), %d1    | load the dividend
-       bpls    1f
-       negl    %sp@(4)         | store abs(dividend)
-1:     movel   %sp@(8), %d0    | load the divisor
-       bpls    2f
-       negl    %sp@(8)         | store abs(divisor)
-2:     eorl    %d1, %d0
-       bpls    3f              | branch if sgn(divisor) == sgn(dividend)
-       moveal  %sp@+, %a0      | pop return address
-       pea     %pc@(Lret)      | push our return address
-3:     jmp     __udivsi3
-Lret:  negl    %d0             | negate quotient
-       jmp     %a0@
diff --git a/Xisop/src/processors/m68k/math/modsi3.s b/Xisop/src/processors/m68k/math/modsi3.s
deleted file mode 100644 (file)
index b042612..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* $Id: modsi3.s,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Matthew Fredette.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-.globl __modsi3
-
-
-
-| NB: this requires that __udivsi3 preserve %a0 and return
-| the modulus in %d1:
-__modsi3:
-       moveal  %sp@+, %a0      | pop return address
-       movel   %sp@(4), %d1    | load the divisor
-       bpls    1f
-       negl    %sp@(4)         | store abs(divisor)
-1:     movel   %sp@, %d0       | load the dividend
-       pea     %pc@(Lret)      | push our return address
-       bpls    2f
-       negl    %sp@(4)         | store abs(dividend)
-       subql   #2, %sp@        | adjust return address
-2:     jmp     __udivsi3
-       negl    %d1             | negate modulus
-Lret:  movel   %d1, %d0        | move modulus into %d0
-       jmp     %a0@
diff --git a/Xisop/src/processors/m68k/math/mulsi3.s b/Xisop/src/processors/m68k/math/mulsi3.s
deleted file mode 100644 (file)
index a4cb7c8..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $Id: mulsi3.s,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Matthew Fredette.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-.globl __mulsi3
-
-__mulsi3:
-       movew   %sp@(6), %d0
-       moveal  %d0, %a0        | save B
-       muluw   %sp@(8), %d0    | %d0 holds B * C
-       movew   %sp@(10), %d1
-       moveal  %d1, %a1        | save D
-       muluw   %sp@(4), %d1    | %d1 holds A * D
-       addw    %d1, %d0        | %d0 holds (B * C) + (A * D)
-       swap    %d0
-       clrw    %d0             | %d0 holds ((B * C) + (A * D)) << 16
-       exg     %a0, %d0        | restore B
-       movel   %a1, %d1        | restore D
-       muluw   %d1, %d0        | %d0 holds B * D
-       addl    %a0, %d0        | final result
-       rts
diff --git a/Xisop/src/processors/m68k/math/udivsi3.s b/Xisop/src/processors/m68k/math/udivsi3.s
deleted file mode 100644 (file)
index 3c3d1da..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/* $Id: udivsi3.s,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Matthew Fredette.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-.globl __udivsi3
-
-__udivsi3:
-       movel   %d2, %sp@-      | save %d2
-       movel   %sp@(12), %d0   | load divisor
-       movel   %sp@(8), %d1    | load dividend
-
-| first, we divide the divisor and dividend by two until 
-| the divisor fits into 16 bits:
-1:     cmpil   #0x10000, %d0
-       bcss    2f
-       lsrl    #1, %d0
-       lsrl    #1, %d1
-       bras    1b
-2:
-
-| now we can do the divide.  to avoid overflow, we have to 
-| do the divide in two parts, high and low, and add the 
-| results together:
-       movew   %d1, %d2        | save low(dividend)
-       clrw    %d1
-       swap    %d1             | %d1 = dividend >> 16
-       divuw   %d0, %d1        | do the high divide
-       moveal  %d1, %a1        | save high divide result
-       movew   %d2, %d1        | concat(remainder, low(dividend))
-       divuw   %d0, %d1        | do the low divide
-       movel   %a1, %d0        | recover high divide result
-       swap    %d0
-       clrw    %d0             | %d0 = finished high divide result
-       andil   #0xffff, %d1    | %d1 = finished low divide result
-       addl    %d1, %d0        | %d0 = quotient guess
-
-| the quotient we have so far is only a guess.  the divide we 
-| did above was really the divide of some dividendB by some 
-| divisorB, where the following hold:
-|
-| (dividend - divisor) <= dividendB <= dividend
-| (divisor / 2) < divisorB <= divisor
-|
-| so our guess quotient cannot be less than our real desired
-| quotient.  however, it might be one too big.
-|
-| to adjust this quotient, we multiply it by the original 
-| divisor and subtract the result from the original dividend.  
-| if the result is nonnegative, our guessed quotient was 
-| correct, and the subtraction result is our remainder.  
-| if the result is negative, our guessed quotient was one 
-| too big, and the subtraction result plus the original 
-| divisor is our remainder.
-|
-| as in mulsi3, we have to do the multiply in stages to avoid 
-| overflow:
-
-       movel   %sp@(12), %d2   | load divisor
-       swap    %d2
-       movel   %d0, %d1
-       muluw   %d2, %d1        | high(divisor) * low(guess)
-       moveal  %d1, %a1        | save high(divisor) * low(guess)
-       swap    %d2
-       movel   %d0, %d1
-       swap    %d1
-       muluw   %d2, %d1        | low(divisor) * high(guess)
-       addl    %a1, %d1
-       swap    %d1
-       clrw    %d1             | %d1 = finished high multiply result
-       moveal  %d2, %a1        | save original divisor
-       muluw   %d0, %d2        | low(guess) * low(divisor)
-       addl    %d1, %d2        | %d2 = guess * divisor
-       
-       movel   %sp@(8), %d1    | load original dividend
-       subl    %d2, %d1        | subtract
-       bccs    3f
-       subql   #1, %d0         | adjust quotient
-       addl    %a1, %d1        | adjust remainder
-3:     movel   %sp@+, %d2      | restore %d2
-       rts
diff --git a/Xisop/src/processors/m68k/math/umodsi3.s b/Xisop/src/processors/m68k/math/umodsi3.s
deleted file mode 100644 (file)
index 37898cf..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/* $Id: umodsi3.s,v 1.1 2003/10/26 21:19:57 mmondor Exp $ */
-
-/*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Matthew Fredette.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-.globl __umodsi3
-
-
-
-| NB: this requires that __udivsi3 preserve the %a0
-| register, and that it returns the modulus in %d1:
-__umodsi3:
-       moveal  %sp@+, %a0      | pop the return address
-       jsr     __udivsi3
-       movel   %d1, %d0        | move the modulus into %d0
-       jmp     %a0@            | return
diff --git a/Xisop/src/processors/m68k/support.h b/Xisop/src/processors/m68k/support.h
deleted file mode 100644 (file)
index 4afe2a3..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/* $Id: support.h,v 1.6 2004/06/03 05:44:05 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Derived from informations from the "Mise en oeuvre du 68000" book.
- * The spl name was inspired from NetBSD SPL(9) man page. The code for
- * these is in support.s
- */
-
-
-
-#ifndef PROCESSOR_M68K_H
-#define PROCESSOR_M68K_H
-
-
-
-#include <common/types.h>
-
-
-
-/* Definitions for optimizations and network byte order support */
-#define _ARCH_BIG_ENDIAN
-#define _ARCH_INT_BITS 32
-/*#define _ARCH_LOWCACHE*/
-/*#define _ARCH_USEINDEXING*/
-
-
-
-/* Abstract datatypes we must provide */
-
-/* A CPU context which can also hold the state of user tasks.
- * Also used as buffer area for setjmp()/longjmp() functions.
- * Note that USP (User Stack Pointer) is actually SP/A7, as seen
- * from supervisor code, which SP/A7 stack is set to SSP (Supervisor
- * Stack Pointer). This means that from supervisor code the special
- * usp related instructions must be used to manipulate the current
- * user stack pointer, but that from userspace this simply is sp which
- * can be manipulated without supervisor access (like in setjmp()/longjmp()).
- */
-typedef struct _ctx {
-    void *a0, *usp;
-    u_int32_t d0, d1, d2, d3, d4, d5, d6, d7;
-    void *a1, *a2, *a3, *a4, *a5, *a6;
-    void *pc;
-    u_int16_t sr;
-    u_int16_t padding;
-} volatile _ctx_t;
-
-/* A simple lock */
-typedef volatile u_int8_t      _lock_t;
-/* A recursive lock */
-typedef int32_t                        _rlock_t;
-
-/* An interrupt priority level context */
-typedef u_int16_t              _ipl_t;
-
-
-
-/* Set interrupt level control functions */
-_ipl_t _spl(u_int16_t);
-#define _spl0()                _spl(0x2000)
-#define _spl1()                _spl(0x2100)
-#define _spl2()                _spl(0x2200)
-#define _spl3()                _spl(0x2300)
-#define _spl4()                _spl(0x2400)
-#define _spl5()                _spl(0x2500)
-#define _spl6()                _spl(0x2600)
-#define _spl7()                _spl(0x2700)
-#define _splhigh()     _spl(0x2700)
-void _splx(_ipl_t);
-
-/* Atomic locking functions. These are SMP safe. */
-void _lock_init(_lock_t *);
-void _lock_acquire(_lock_t *);
-void _lock_release(_lock_t *);
-bool _lock_try(_lock_t *);
-bool _lock_available(_lock_t *);
-
-/* Atomic recursive locking functions. The same number of release operations
- * must be performed for the lock to become available again, and there can
- * be any number of concurrent lockers.
- */
-void _rlock_init(_rlock_t *);
-void _rlock_acquire(_rlock_t *);
-void _rlock_release(_rlock_t *);
-bool _rlock_try(_rlock_t *);
-bool _rlock_available(_rlock_t *);
-
-/* Efficient byte order conversion functions */
-u_int16_t _bswap16(u_int16_t);
-u_int32_t _bswap32(u_int32_t);
-
-/* Function to create a new CPU context for a task */
-void _ctx_init(_ctx_t *, u_int32_t *, size_t, void *);
-
-/* Function to put the CPU in idle mode until next interrupt occurs.
- * Restricted to supervisor mode.
- */
-void _idle(void);
-
-/* Useful to call Xisop main() from port-specific initialization code */
-void _usermode(int (*)(void));
-
-
-
-#endif
diff --git a/Xisop/src/processors/m68k/support.s b/Xisop/src/processors/m68k/support.s
deleted file mode 100644 (file)
index 990d9a0..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/* $Id: support.s,v 1.4 2004/01/30 07:08:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-.globl _spl, _splx
-.globl _lock_init, _lock_acquire, _lock_try, _lock_available, _lock_release
-.globl _rlock_init, _rlock_acquire, _rlock_try, _rlock_release, _rlock_available
-.globl _bswap16, _bswap32
-.globl _ctx_init
-.globl setjmp, longjmp
-.globl _idle, _usermode
-
-.text
-
-
-| _spl_t _spl(_spl_t)                  _spl_t == u_int16_t
-|
-_spl:  movew   %sr, %d0
-       movew   %sp@(6), %sr
-       rts
-
-
-| void _splx(_spl_t oldstate)
-|
-_splx: movew   %sp@(6), %sr
-       rts
-
-
-| void _lock_init(_lock_t *lock)       _lock_t == u_int8_t
-| Used to create/init new locks
-|
-_lock_init:
-       movel   %a0, %sp@-
-       moveal  %sp@(8), %a0
-       clrb    %a0@
-       moveal  %sp@+, %a0
-       rts
-
-
-| void _lock_acquire(_lock_t *lock)
-| Blocks current CPU in a loop until lock is obtained
-|
-_lock_acquire:
-       movel   %a0, %sp@-
-       moveal  %sp@(8), %a0
-1:     tas     %a0@
-       bnes    1b
-       moveal  %sp@+, %a0
-       rts
-
-
-| bool _lock_try(_lock_t *lock)
-| Attempts to obtain lock, but returns immediately with TRUE/FALSE result
-|
-_lock_try:
-       movel   %a0, %sp@-
-       moveal  %sp@(8), %a0
-       tas     %a0@
-       beqs    1f
-       clrl    %d0
-       moveal  %sp@+, %a0
-       rts
-1:
-       moveq   #1, %d0
-       moveal  %sp@+, %a0
-       rts
-
-
-| bool _lock_available(_lock_t *lock)
-| Returns 1/TRUE if the lock is currently free, or 0/FALSE if it is locked.
-| Note that this should not be used to attempt to obtain the lock using two
-| steps (see _lock_try() above for this). It is useful to simply know if
-| it is locked, nothing else. Useful for the scheduler on/off switch.
-|
-_lock_available:
-       movel   %a0, %sp@-
-       moveal  %sp@(8), %a0
-       btst    #7, %a0@
-       bnes    1f
-       moveq   #1, %d0
-       moveal  %sp@+, %a0
-       rts
-1:
-       clrl    %d0
-       moveal  %sp@+, %a0
-       rts
-
-
-| void _lock_release(_lock_t *lock)
-| Releases a previously acquired lock
-|
-_lock_release:
-       movel   %a0, %sp@-
-       moveal  %sp@(8), %a0
-       clrb    %a0@
-       moveal  %sp@+, %a0
-       rts
-
-
-| void _rlock_init(_rlock_t *rlock)    _rlock_t = int32_t
-| Initializes a recursive lock
-|
-_rlock_init:
-       movel   %a0, %sp@-
-       moveal  %sp@(8), %a0
-       clrl    %a0@
-       moveal  %sp@+, %a0
-       rts
-
-
-| void _rlock_acquire(_rlock_t *rlock)
-| Acquires the lock, recursively
-|
-_rlock_acquire:
-       movel   %a0, %sp@-
-       moveal  %sp@(8), %a0
-       addql   #1, %a0@
-       moveal  %sp@+, %a0
-       rts
-
-
-| void _rlock_release(_rlock_t *rlock)
-| Releases the lock. _rlock_acquire() and _rlock_release() instances must pair
-| for the lock to eventually be available again.
-|
-_rlock_release:
-       movel   %a0, %sp@-
-       moveal  %sp@(8), %a0
-       subql   #1, %a0@
-       moveal  %sp@+, %a0
-       rts
-
-
-| bool _rlock_try(_rlock_t *rlock)
-| Atomically acquires the lock like _rlock_acquire(), but returns TRUE if
-| we then are the only locker. Otherwise, releases the lock back and return
-| FALSE. Obviously, if we are the only locker, the _rlock_t counter will be
-| one (1). This allows to perform an atomic
-| _rlock_available() + _rlock_acquire() pair.
-|
-_rlock_try:
-       movel   %a0, %sp@-
-       moveal  %sp@(8), %a0
-       moveq   #1, %d0
-       addql   #1, %a0@
-       cmpl    %a0@, %d0
-       beqs    1f
-       subql   #1, %a0@
-       clrl    %d0
-1:     moveal  %sp@+, %a0
-       rts
-
-
-| bool _rlock_available(_rlock_t *rlock)
-| Returns TRUE if the lock is available, or if FALSE if there are any lockers.
-|
-_rlock_available:
-       movel   %a0, %sp@-
-       moveal  %sp@(8), %a0
-       clrl    %d0
-       cmpl    %a0@, %d0
-       bnes    1f
-       moveq   #1, %d0
-1:     moveal  %sp@+, %a0
-       rts
-
-
-| u_int16_t _bswap16(u_int16_t)
-| Swaps the order of the two bytes held in the supplied 16-bit word
-|
-_bswap16:
-       movew   %sp@(6), %d0
-       rorw    #8, %d0
-       rts
-
-
-| u_int32_t _bswap32(u_int32_t)
-| Reverses the order of the four bytes held in the supplied 32-bit word
-| First cause a 16-bit byte swap, then perform a 16-bit word swap within the
-| 32-bit word, and then perform another 16-bit byte swap.
-|
-_bswap32:
-       movel   %sp@(4), %d0
-       rorw    #8, %d0
-       swap    %d0
-       rorw    #8, %d0
-       rts
-
-
-| void _ctx_init(_ctx_t *, u_int32_t *sp, size_t sz, void *pc)
-| Creates a new CPU context which will use specified SP and PC pointers.
-| Note that SP must be pointing at end of stack area, as it grows upwards.
-|
-_ctx_init:
-       moveml  %a0/%d0, %sp@-  | Save a0/d0
-       moveal  %sp@(12), %a0   |               _ctx_t *
-       clrl    %a0@+           | A0
-       movel   %sp@(16), %a0@  | A7/USP        u_int32_t *
-       movel   %sp@(20), %d0   |               size_t
-       addl    %d0, %a0@+      | A7/USP
-       clrl    %a0@+           | D0
-       clrl    %a0@+           | D1
-       clrl    %a0@+           | D2
-       clrl    %a0@+           | D3
-       clrl    %a0@+           | D4
-       clrl    %a0@+           | D5
-       clrl    %a0@+           | D6
-       clrl    %a0@+           | D7
-       clrl    %a0@+           | A1
-       clrl    %a0@+           | A2
-       clrl    %a0@+           | A3
-       clrl    %a0@+           | A4
-       clrl    %a0@+           | A5
-       clrl    %a0@+           | A6
-       movel   %sp@(24), %a0@+ | PC            void *
-       clrl    %a0@            | SR + padding
-|      clrw    %a0@+           | SR
-|      clrw    %a0@            | 16-bit 32-bit padding
-       moveml  %sp@+, %d0/%a0  | Restore d0/a0
-       rts
-
-
-| int setjmp(jmp_buf);
-| We can manipulate SP/USP/A7 from user state without problems. We do not need
-| to manipulate SR. We can safely run in usermode.
-| The supplied jmp_buf is actually a pointer to a _ctx_t. We must return 0
-| normally, but must return the value supplied to longjmp() when it is called.
-| To do this, we zero D0, save context to jmp_buf, and return. longjmp() will
-| load that context back and set D0 to the wanted value before returning.
-|
-setjmp:
-       movel   %a0, %sp@-              | Save A0 (4 bytes) to current stack
-       moveal  %sp@(8), %a0            | Pointer to _ctx_t
-       clrl    %d0                     | Default return value to 0
-       lea     %a0@(66), %a0           | Pos now after pc
-       movel   %sp@(6), %a0@-          | PC norm at %sp@(2), we saved 4 bytes
-       moveml  %a1-%a6/%d0-%d7, %a0@-  | Save A6-A1, D7-D0
-       movel   %sp, %a0@               | Save A7/USP (without saved 4 bytes)
-       addql   #4, %a0@-
-       movel   %sp@+, %a0@-            | Restore A0 and save it
-       rts
-
-
-| void longjmp(jmp_buf, int)
-| No need to save registers since we are loading the supplied state.
-| We technically never return, we however make sure to load D0 (which
-| will become setjmp() return value) with the supplied value argument.
-|
-longjmp:
-       moveal  %sp@(4), %a0            | _ctx_t pointer
-       movel   %sp@(8), %d0            | Return value for setjmp()
-       addql   #4, %a0                 | Now at usp
-       moveal  %a0@+, %sp              | Restore context stack pointer
-       addql   #4, %a0                 | Now at d1
-       moveml  %a0@+, %d7-%d1/%a6-%a1  | Load registers from context
-       movel   %a0@, %sp@(2)           | Restore return PC
-       moveal  %a0@(-68), %a0          | Restore A0
-       rts                             | Resume at setjmp() saved PC
-
-
-| void _idle(void)
-| Puts CPU in sleep mode until next interrupt occurs. Useful to not use 100%
-| CPU time and overheat when all tasks are idle. Also saves alot of power
-| on battery powered systems. Restricted to supervisor mode.
-|
-_idle:
-       movew   %sr, %sp@-
-       stop    #0x2000
-       movew   %sp@+, %sr
-       rts
-
-
-| void _usermode(int (*)(void));
-| Useful for port-specific init code to call Xisop main()
-| Permits to switch from supervisor mode to usermode and jump to the specified
-| function. The current supervisor stack is used to setup the user stack (US).
-| The user stack we create is 1024 bytes. Obviously, the SS should have enough
-| room for this. The function we jump to is expected to only perform minor
-| initialization, like to start the first Xisop task, with it's own stack.
-| Used to call Xisop's main() function from init.c
-|
-_usermode:
-       moveal  %sp@(4), %a0    | Address to jump to
-       movel   %sp, %a1
-       lea     %sp@(-1024), %sp
-       movel   %a1, %usp
-       andiw   #0xdfff, %sr    | Switch to usermode
-       jmp     %a0@
diff --git a/mmsoftware/BUGS b/mmsoftware/BUGS
deleted file mode 100644 (file)
index 5cc781d..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-$Id: BUGS,v 1.8 2003/01/10 06:45:59 mmondor Exp $
-
-
-
-- Fix anoncvs pserver
diff --git a/mmsoftware/LICENSE b/mmsoftware/LICENSE
deleted file mode 100644 (file)
index 786ba63..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-Copyright (C) 2000-2004, Matthew Mondor
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-     This product includes software written by Matthew Mondor.
-4. The name of Matthew Mondor may not be used to endorse or promote
-   products derived from this software without specific prior written
-   permission.
-5. Redistribution of source code may not be released under the terms of
-   any GNU Public License derivate.
-
-THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/mmsoftware/TODO b/mmsoftware/TODO
deleted file mode 100644 (file)
index 45c5e3d..0000000
+++ /dev/null
@@ -1,387 +0,0 @@
-$Id: TODO,v 1.46 2005/03/09 08:55:28 mmondor Exp $
-
-
-
-SITE/
-=====
-
-- Write a system, maybe using /bin/sh and/or gmake, to create the software
-  section of the site automatically using a simple to maintain file or set
-  of files as a database of the projects. It potentially also could be used
-  to automatically package a new version of the software, after tagging the
-  CVS repository.
-- It would be nice to automate the freshmeat update, I will see if it can
-  be done safely, otherwise I shall need to update it manually on their
-  site.
-
-
-
-MMLIB/MMREADCFG
-===============
-
-- Should also allow some keywords to embed other keywords or serve as
-  delimiters. For instance, for each network interface defined,
-  options which are now global could be set on an interface-basis.
-  This probably implies providing the library with a structure to fill
-  with field offsets, or such. I want the application to afterwards be
-  able to very quickly access any configuration data and not have to
-  perform hashtable lookup operations.
-  An implementation could be provided with various array sets similar to
-  the current one. Whenever a duplicate entry occurs one those a new
-  entry would be created with the defaults, and be filled from now on...
-- An apache/proftpd style configuration file format is envisagable.
-
-
-
-MMFTPD
-======
-
-- Use a custom stack on the heap to determine the size of a home directory,
-  rather than using standard recursion on the stack. We would then use an
-  iterative, safer method.
-- Reuse mmfd handle for file_out()
-- It would be nice to support at least part of rfc2228, that is, secure
-  authentication FTP extension.
-- Modularize user authentication, abstracting the checkuser() function, and
-  of course provide a way for the user to specify which one to use at compile
-  time. An authentication module using MySQL for instance should not require
-  the software to need libmysqlclient library if plain-file authentication is
-  used instead (/etc/mmftpdpasswd). Moreover, per-module options will be
-  required, location of file for plainfile, and DB options for MySQL, etc).
-- Work a way out to have per-host/iface options and users
-- Implement a global upload directory, common to all users via /upload, which
-  would be configurable for each account...
-- Write an ssl-httpd dedicated to remotely managing mmmail and mmftpd
-
-- When NetBSD scheduler activations gets released as stable, I should
-  be able to convert the daemon to use POSIX Threads API instead of GNU Pth
-  which it currently uses. There however seems to be lacking important
-  functionality in that API, particularly in the fd multiplexing area.
-  I will have to provide an efficient message passing system among threads,
-  and a way to have a thread sleep while waiting for the following conditions:
-  optional timeout, fd status change, message available.
-  The only current way which would seem to solve those issues would be to
-  use more file descriptors and implement everything to affect fds. This
-  however proves an important lack in POSIX Pthread API. I need to investigate
-  on more efficient alternatives. pth's poll_ev() and pth_msg*() currently
-  solve those issues.
-  A possible alternative would be to have a special thread which could serve
-  as an events manager, using a unified message system which would describe
-  events occuring... BSD kqueue would be ideal, but are not portable.
-  Maybe I could use libevent library or provide my own...
-  XXX It seems that libevent cannot be expected to be thread-safe (will only be
-  on some systems, since it can fallback to select()/flock() where necessary).
-- If only message passing was required, conditional variables and/or mutexes
-  could be used to implement waiting, etc. However, we also need to listen for
-  filedescriptor events... And, we must support a timeout, which would have to
-  interrupt message port and/or filedescriptor polling. The main problem
-  involving an additional or several filedescriptors to implement message
-  passing is that system calls are expensive. If we only needed to pass a very
-  short atomic message through a single filedescriptor only for required
-  operations involving polling, perhaps that it would be decent...
-  POSIX threads condition variables support timeouts...
-- Complete libpth event/message replacement to port mmftpd and mmserver to
-  new NetBSD threads (and POSIX API)
-
-
-
-MMMAIL
-======
-
-- Have mmsmtpd start a daemon process to call the MySQL OPTIMIZE command on
-  the database tables once in a while, asynchroneously.
-- Because initializing a new hashtable_t is rather expensive, we do not want
-  to have to initialize one per new client connection for RCPT storage.
-  Either we keep using the linear system for RCPTs like we are doing now,
-  or that we switch to a system using a shared table for the whole process,
-  with specialized hash and compare functions so that two fields be taken
-  into consideration: 1) the unique ID for this connection and 2) the actual
-  RCPT address. This however could have some disadventages. For instance,
-  iterating through the whole hashtable_t would be required to post a message,
-  and the same would apply to free the RCPT entries for a session after it
-  was transfered... We could run it once only and free those entries during
-  the same step however. The current linear method is fine as long as we
-  restrict the number of allowed RCPTs to a sane value and that most posts
-  do not require a high number of RCPTs.
-  NOTE: We now have hashtable_init2() in mmhash(3) which is faster.
-
-- Some basic relaying support should be implemented; simpler than the one
-  targetted at mmmail2 (which I current fail to have time to implement, to
-  achieve such a new project from scratch, I would need to have it sponsored).
-  What I currently need is basic relaying support, as well as a simple
-  mailing list facility (like to provide support for my software). For this,
-  a few new tables could be implemented... Mailing list addresses as well as
-  their subscriber addresses; Relaying queue; Allowed IP address blocks and/or
-  hostname patterns to allow relaying for.
-  QUEUE MANAGEMENT - Notes pertaining to mmsmtpd/mmrelayd interaction and the
-  ================   mail queue.
-  - mmsmtpd queues mail which is to be relayed (this prevents mail from getting
-    lost in case of relaying problems, and it appears logical to do because
-    mmsmtpd is the daemon reading the mail and saving the message file.
-    mmsmtpd then attempts to notify mmrelayd that a new message was queued.
-    We do this in order to allow mmrelayd to update its schedule as fast as
-    possible instead of only at scheduled queue queries. Moreover, it can
-    prevent mmrelayd from having to potentially query large datasets frequently
-    in case of large queues (this assumes that one notification message is
-    transfered per queued message, and that the notification holds the
-    necessary information to prefent mmrelayd from having to perform an SQL
-    query to add the message to the schedule).
-  - mmrelayd would maintain an in-memory schedule as much as possible to
-    minimize the frequency of SQL queries. An initial large query would be made
-    to create the schedule when launched. Notification messages from mmsmtpd
-    would serve to schedule new elements without an SQL query. An SQL query
-    would however be made to update an entry for a message for which a relay
-    attempt was made; Either to discard the entry after successful relaying,
-    or to update its information if it has to be rescheduled due to failing.
-    Of course, a discard would also occur eventually after too many failures
-    or specific forms of immediate failures. The sender of the message could
-    potentially be notified of these error events, by queueing a new message.
-  - Relaying failure replies could probably be sent through mmsmtpd from
-    mmrelayd via standard SMTP. Or, for enhanced performance, we may want
-    to queue the message ourselves and schedule it to avoid unnecessary
-    overhead.
-  - The scheduler would consist of a main thread, and a number of dedicated
-    threads in a ready pool could perform actual relaying of scheduled events.
-    The main scheduler thread would also be the one monitoring the
-    notifications socket to schedule new events. If we decide to queue
-    ourselves error reply messages, this also could be done by the same thread.
-    Otherwise, threads in the ready pool would be assigned to route the
-    messages to mmsmtpd in case of failure.
-  - My current ready threads pool implementation was made for asynchronous
-    dispatching of tasks. I will need to ensure in this case that the master
-    thread can dispatch multiple tasks to threads asynchroneously, but to then
-    also be able to process return results as soon as possible whenever a
-    thread ends its task. This can be done using interthread messaging as well.
-  - I am currently evaluating if a custom DNS cache is worth implementing.
-    With caching DNS servers, the overhead of lookups shouldn't be too bad.
-    It however is clear that lookup must be done by a concurrent thread rather
-    than in the main scheduler thread.
-  - It would be nice to attempt to schedule multiple messages for a common
-    destination SMTP server together to minimize TCP connection establishment
-    overhead when possible. It also would be nice to use multiple RCPTs for
-    messages which need to be routed to multiple destinators which are local
-    to the same SMTP server.
-
-- PAGE (and in the future PLIST) should be able to remember the current message
-  worked on (or LIST position) so that between pages TOP, NEXT, PREV, BOTTOM,
-  JUMP special commands could be used without having to always specify the
-  number of lines of the terminal, etc.
-
-- Fix mmmail timestamps to be "unsigned int(11)" ?
-       -- no php, even likes that :)
-        mktime() to get current timestamp and date("r", timestamp) to turn
-        timestamp into RFC 822 formatted date.
-  SUGGEST:
-       mysql> select unix_timestamp(now());
-       +-----------------------+
-       | unix_timestamp(now()) |
-       +-----------------------+
-       |            1041000120 |
-       +-----------------------+
-       1 row in set (0.00 sec)
-
-       mysql> select from_unixtime(1041000120);
-       +---------------------------+
-       | from_unixtime(1041000120) |
-       +---------------------------+
-       | 2002-12-27 09:42:00       |
-       +---------------------------+
-       1 row in set (0.00 sec)
-
-- Fix mmmail to use table locking rather than global locking?
-       -- locking tables:
-        LOCK TABLES `mail` write, `box` write;
-        INSERT INTO MAIL (...) VALUES (...);
-        UPDATE BOX (....) VALUES (....);
-        UNLOCK TABLES;
-       XXX Unfortunately it seems that this cannot be done in a thread-safe
-           way; The whole process would lock until lock could be obtained.
-           So the current method seems best for now.
-            It would be working if every thread had a connection to the server,
-            but we currently are using a single persistent connection to MySQL
-            for the whole process.
-
-- Perhaps add UNSIGNED attribute to all mmmail SQL columns which could use
-  it; This would also require C functions modifications however.
-
-
-
-MMSTATD
-=======
-
-- Modify the librarian so that it could still continue to process new logs
-  while a client is still reading a statistical report as it's own pace.
-  For this, a buffer could atomically be filled with the request, which
-  would then be spit out at the speed the client reads it while still checking
-  for new logs using poll(2). Possibly also allow support for multiple clients
-  requesting statistics at the same time. This would be a good prelude to
-  eventually allowing statistical reports via TCP.
-- ADD SUPPORT FOR BETTER OUTPUT MODES TO MMSTAT CLIENT
-  Default would be human format with only necessary columns and name sorting.
-  Then -n could be used for unix timestamps, -? for no top/botom header(s),
-  -v for verbose +d<dateformat> +c<columnsformat> etc...
-  Or, defaults to the current format and:
-  -h human etc...
-- It would probably be nice to implement namespaces, and support features such
-  as export/import/merge of key sets additionnal to rotation.
-- Some remote functionality should be implemented. It would be nice to be able
-  to safely allow statistical reports remotely, and to isolate the
-  key rotation requests into a separate administration socket.
-  - There then could be three separate type of sockets: update, admin, stats
-  - Or, remote persistant connections under SSL could be invisaged so that it
-    be safe on the network, even instead using a datagram socket for updates.
-  - It also would be possible to let the administrator decide which keys should
-    be created, and have the update socket only allow to update existing
-    counters.
-  - If remote operation was supported, it would be important for the report
-    data to be endian-independant. This is still a problem using 64-bit
-    variables as most libc do not comport functions for host to network or
-    network to host convertion of 64-bit data types (NetBSD does, of course,
-    but Linux, another target, does not).
-
-NEW DESIGN
-
-mmstat(3) and mmstatd(8) would be most useful if the server could be remote,
-and if it comported users and authentication. Here are ideas on how this could
-be done without degrading performance of the clients much. Because if we used
-TCP and the server was remote, there is a possibility for delays caused by
-network problems or latency. This must not happen since the clients must be
-able to update statistic counters at a high frequency without expecting a
-delay.
-
-Performance issues
-
-- The client library could start a daemon process, to which atomic requests
-  would be sent to by mmstat() function calls. The daemon would establish
-  a persistent connection to the mmstatd(8) server. This connection could then
-  be TCP. The communication channel could even be encrypted since the daemon
-  process would dispatch requests as fast as it can, without slowing down
-  mmstat() calls. The special process could handle encryption, endian byte
-  order conversions, and the TCP stream. It also could have it's own signal
-  handlers and timers to regularily attempt to flush the buffers if it cannot
-  do it right away after a request.
-- Another possibility would be to use a non-blocking socket, with buffering.
-  At every mmstat() call, or when a timeout occurs, an attempt would be made
-  to flush the buffer. If EAGAIN is returned, we keep the buffer and will
-  retry later on. This approach may be less complex than the previous one
-  to implement. However, if encryption is being used, and that TCP is used,
-  it is certain that mmstat() calls cannot reach the performance which the
-  current library implementation yields. If we simply used rc4, which is a
-  very fast cypher, performance may be reasonable for general purpose use.
-  However, because we deal with multiple systems on a network, endian
-  conversions will also need to be performed on the values sent over the
-  protocol, another operation which will reduce performance on i386 and other
-  little endian byte order architectures. Moreover, if we used a timer to
-  flush the buffer at regular intervals if it could not be flushed immediately,
-  we could result in clobbering the caller process by a signal handler or such.
-
-Data integrity issues
-
-- Using any of the above methods, it would be tricky to be able to have the
-  same data integrity than with the current implementation. The reason is that
-  two local processes sending eachother AF_LOCAL datagrams almost guarantee
-  that they obtain their data, and with very low latency. The mmstatd(8)
-  logger process which permits high data integrity with crash recovery
-  would almost need to be reproduced at the client library level as well
-  if we were to achieve the same reliability. This also means that persistent
-  files on the filesystem would need to be maintained by the client library
-  for each process.
-- A possibility would be to use a local mmstatd(8) proxy or similar system
-  which could provide crash recovery and establish links with other mmstatd(8)
-  servers. Perhaps that we could derive a distributed system of sorts over this
-  system. mmstatd servers would have authenticated links with other mmstatd
-  servers to which it would forward requests intended for them. Either they
-  would all synchronize to the same data, or that a form of routing would be
-  used, with addresses. If such a system is to be implemented, it would be
-  useful to create an API to allow a general purpose messaging network
-  over this principle. I wrote notes about a CORBA-like system with better
-  performance and more secure framework somewhere, I should read those notes
-  again and attempt to implement something out of them. Basically, it allows
-  to morph network topology, where nodes may be part of a same process, of
-  other processes on the same computer, where shared memory and/or AF_LOCAL
-  could be used, of remote computers, where TCP persistent links with
-  authentication and encryption could be used.
-- A simpler system might be to simply allow mmstatd(8) to mirror to other
-  fixed mmstatd(8) servers when remote functionality is needed... The librarian
-  would forward the log entries it processes in network endian with the
-  other mmstatd(8) server it connects to...
-
-Allowing mmstatd(8) to work in proxy or master mode might be the simplest way
-to implement the system. mmstatd(8) consists of two processes, the logger,
-getting messages and logging them to file, and the librarian, reading those
-logs from file and effecting the database changes. The librarian could easily
-be convereted into a forwarder, where instead of being commited to the memory
-database, packets would be forwarded over to a master mmsmtpd. It however
-would be most useful to support namespaces. This also means that mmsmtpd must
-be able to accept remote clients (slave mmsmtpd clients). We then also would
-want authentication and encryption. We however still always have a problem
-then where user credentials checking should be implemented... Also, counters
-reports could only be obtained from the master site, locally, unless
-especially implemented with remote functionality as well.
-
-Ultimately, if the client side (or application-specific side) cacheing,
-recovery and forwarding issues are solved, it would be ideal if mmstatd
-supported multiple persistent client connections, through which it could allow
-both updates and queries. It then would need to support application-specific
-user authentication and at least RC4 encryption. Ideally, each user would be
-allowed a number of namespaces they could manage, which would further allow
-better administration. If applications required to perform both updates and
-queries at the same time in parallel, they would probably need a persistent
-handle per parallel thread/process.
-
-
-
-MMLIB/MMFD
-==========
-
-- Should probably be called mmio
-- Abstract read/write/?poll functions to allow the mmfd library to be portable
-  under other environments (I.E. kernel code)? Hmm this would make it a little
-  slower but may be worth it.
-
-
-
-MMMAIL2
-=======
-
-- Review design notes
-- Design the modularized interface for storage abstraction
-- Check dbmail.org design in case it may give good ideas for mmmail2 design,
-  (PowerMail).
-- Write the whole thing
-
-
-
-MMLIB/MMSERVER2
-===============
-
-- Think about if it would be possible to have per-process caches with a means
-  to propagate changes among the processes, rather than simply using a single
-  socket-specific cache and single global hostname cache with locks. This could
-  provide potential speed optimizations, especially on multiprocessor systems.
-  The same is true for locks which are used to allocate and free resources with
-  mmpool(3). Perhaps that per-process caches would be great, however this needs
-  to be implemented with care. How would another process free a node allocated
-  by this process are questions which come into play. Check slab allocator
-  implementations using SMP optimizations with magazines and per-CPU caches.
-  Of course, my system would not deal with CPU-based caches, but with process
-  based ones instead, with the same ideas.
-
-
-
-MMLIB/MMPOOL
-============
-
-- CPU specific memory caches and magazines would be nice, but also require
-  specialized kernel support for such. I won't care about this for now.
-  It however might be possible to do this on a per-process basis, I'll have to
-  think about it a bit. It would prevent having to use synchronization locks
-  when multiple processes are shareing the same pool, in order to gain more
-  performance.
-
-
-
-MMANONCVS
-=========
-
-- Add section in troubleshooting about errors when upgrading glibc
diff --git a/mmsoftware/apache-mmstat/GNUmakefile b/mmsoftware/apache-mmstat/GNUmakefile
deleted file mode 100644 (file)
index fb4b262..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-# $Id: GNUmakefile,v 1.2 2004/05/31 06:19:17 mmondor Exp $
-
-MMLIBS := $(addprefix ../mmlib/,mmlog.o mmpool.o mmhash.o mmreadcfg.o \
-mmstat.o mmstring.o)
-
-OBJS := apache-mmstat.o
-
-CFLAGS += -Wall
-
-
-all: apache-mmstat
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I../mmlib -o $@ $<
-
-apache-mmstat: $(MMLIBS) $(OBJS)
-       cc -o $@ -lc $(OBJS) $(MMLIBS)
-
-install:
-       install -cs -o 0 -g 0 -m 550 apache-mmstat /usr/local/libexec
-       install -c -o 0 -g 0 -m 444 apache-mmstat.8 /usr/local/man/man8
-
-clean:
-       rm -f apache-mmstat $(OBJS) $(MMLIBS)
diff --git a/mmsoftware/apache-mmstat/apache-mmstat.8 b/mmsoftware/apache-mmstat/apache-mmstat.8
deleted file mode 100644 (file)
index 26be0c6..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-.\" $Id: apache-mmstat.8,v 1.5 2004/05/05 10:01:55 mmondor Exp $
-.\"
-.\" Copyright (C) 2003, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd July 1, 2003
-.Dt APACHE-MMSTAT 3
-.Os mmsoftware
-.Sh NAME
-.Nm apache-mmstat
-.Nd mmstat(3) facility support for apache
-.Sh SYNOPSIS
-.Nm
-.Ar user
-.Ar group[,group...]
-.Ar mmstatconf
-.Ar allow
-.Sh DESCRIPTION
-.Nm
-primarily was written to be used with the apache HTTP server but could well be
-used with other web server software, as long as they can adapt their logging
-output and automatically pipe logs through it. The goal of this utility is to
-provide a frontend to the
-.Xr mmstat 3
-library for apache to maintain on-the-fly global and virtual-host specific
-statistical counters via the
-.Xr mmstatd 8
-daemon. This
-.Nm mmstat
-facility was written by Matthew Mondor and is available at
-.Nm http://mmondor.gobot.ca/software.html .
-.Pp
-Apache comes with an automatic log rotation utility called rotatelogs. It
-also supports the capability of piping logs to it, and other applications,
-starting the logfile name with a pipe '|' character. Apache also allows to
-control the format of the log lines it generates and their scope (global or
-vhost specific).
-.Nm
-exploits this flexibility.
-.Pp
-Maintaining these counters may serve several purpose, it can be used as-is,
-or in conjunction with a graph system such as rrdtool using the
-.Xr mmstat 8
-client as input source, etc.
-.Pp
-.Ar user
-specifies the name or ID of the user to which the process should be set when
-revoking superuser privileges.
-.Pp
-.Ar group
-consists of a group, or comma-separated list of group names or IDs which
-the process should become part of when revoking superuser privileges.
-No spaces should separate the comma-separated list if more than one group
-is specified.
-.Pp
-.Ar mmstatconf
-should consist of the absolute path to an
-.Xr mmstatd.conf 5
-configuration file which will be used to access the proper
-.Xr mmstatd 8
-copy.
-.Pp
-.Ar allow
-specifies the verbosity of wanted statistics. Here is a the meaning of each
-allowed letter. By default, nothing is done, when each letter will enable
-a feature:
-.Bl -tag -width indent -offset indent
-.It Nm G
-Record global statistics such as:
-.Bd -literal -offset indent
-apache|total|bytes
-apache|total|errors
-apache|total|requests
-apache|total|denied
-apache|total|errors
-apache|denied|<address>
-.Ed
-.Pp
-Several of those may be enabled or disabled depending on other specified
-options to
-.Ar allow .
-.It Nm V
-Keep virtual-host specific statistics such as:
-.Bd -literal -offset indent
-apache|vhost|<vhost>|GET|<file>
-apache|vhost|<vhost>|agent|<useragent>
-apache|vhost|<vhost>|bytes
-apache|vhost|<vhost>|referer|<referer>
-apache|vhost|<vhost>|requests
-apache|vhost|<vhost>|denied
-apache|vhost|<vhost>|denied|<address>
-apache|vhost|<vhost>|errors
-apache|vhost|<vhost>|errors|<address>
-.Ed
-.Pp
-Several of these may be enabled and disabled depending on the other specified
-.Ar allow
-options.
-.It Nm R
-Record statistics on vhost-specific referers (only possible if
-.Nm V
-was also enabled).
-.It Nm U
-Keep counters on vhost-specific user-agent strings (only allowed if
-.Nm V
-is enabled).
-.It Nm A
-Allows IP address of offending HTTP clients to be kept. The reports which have
-<address> are affected.
-.It Nm F
-Enables stats keeping of transfers (the entries with |GET|). Only valid with
-.Nm V .
-.El
-.Pp
-.Sh SECURITY CONSIDERATIONS
-First, apache launches piped applications, such as
-.Nm
-as the superuser (user id 0, root). Because of this, several important
-steps have to be taken by both the administrator and the application:
-.Ss What the application does
-.Bl -tag -width indent -offset indent
-.It SIGSEGV signal handler
-To prevent a possible segmentation fault violation from causing a process core
-dump, a signal handler is setup which immediately calls exit(3).
-.It File descriptor cleanup
-Only the stdin (0) file descriptor is kept open, and stdout as well as stderr
-(1, 2) are redirected to /dev/null.
-.It Privilege revokation
-One of the first steps which
-.Nm
-performs is to drop it's privileges to the user and group(s) specified on the
-command line arguments.
-.El
-.Bl -tag -width indent -offset indent
-.Ss What the administrator should be aware of
-.It The command line arguments origin
-It becomes obvious that the command line arguments should be trustable, and
-as such should be specified in httpd.conf, which should only be modifiable by
-the superuser.
-.It The command path
-The apache configuration file should always ensure to also specify the
-absolute full path to the installed
-.Nm
-application, and that this command cannot be modified by the users. It also
-should not bear any of the setuid or setgid bits in it's permissions. It
-can itself safely assign itself to the specified user and groups for each
-running copy.
-.It The target Xr mmstatd 8
-Also specified on the command line arguments by the apache process is the
-configuration file of the targetted
-.Xr mmstatd 8
-daemon which should receive the request. This allows alot of flexibility;
-Users can each run their own
-.Xr mmstatd 8
-if wanted, or the administrator can decide to use a specific dedicated one,
-or the system one, etc. See the
-.Xr mmstat 3 ,
-.Xr mmstatd 8
-and
-.Xr mmstat 8
-man pages for more information.
-.El
-.Pp
-A second step which has to be taken in consideration is that the log lines
-which apache generates include fields which are supplied by the HTTP clients,
-and as such are untrustable. To cope with this,
-.Nm
-observes the following strategy:
-.Bl -tag -width indent -offset indent
-.Ss How the lines read from stdin are parsed
-.It Superuser privileges are revoked
-The permissions are dropped before even starting to read lines from apache via
-stdin.
-.It Line buffer not on the stack
-The input line buffer into which lines are read from stdin is allocated using
-.Xr malloc 3
-so that it is not located on the stack. Although
-.Xr fgets 3
-is used with a specified limit to not exceed the buffer, if a line overflow
-ever occurs either at input or post processing, it would be much more likely
-to cause a segmentation fault generating a SIGSEGV signal which would kill
-the application immediately and let apache restart it, rather than allowing
-a third party to modify or trash the actual program code and result in
-unexpected behavior.
-.It Line sanity checking
-Any lines which does not have the '\\n' terminator are dropped, which are most
-likely the result of a previous line which was unreasonably long or could not
-be parsed properly. Apart from the terminating '\\n', any line which has
-abnormal control characters (< ASCII 32) is immediately ignored.
-.Pp
-Special characters which may cause problems either for
-.Xr mmstat 3
-key naming
-or for C
-.Xr stdarg 3
-are substituted by other characters.
-.Pp
-Because apache guarantees no safe field separation character which could not
-be supplied by the HTTP client and cause parsing problems, the '|' character
-was chosen as field separator.
-.Nm
-initially locates and separates the line at '|' characters and then drops it
-immediately if it does not have the expected separators.
-.Pp
-The last expected field consists of the HTTP response code which was sent to
-the client. If the number of columns matched, this value is evaluated for
-valid common response codes, and is ignored if it appears to not conform.
-.Pp
-Ultimately, if all the sanity checks have succeeded, the
-.Fn mmstat_transact
-and
-.Fn mmstat
-functions of the
-.Xr mmstat 3
-library are used to delegate statistics in the form of logs to the
-.Xr mmstat 8
-daemon which normally already runs under another unprivileged user
-(usually mmstatd user, or an arbitrary normal user which runs mmstat and
-requests the administrator to run apache-mmstat for statistical book keeping).
-The
-.Xr mmstat 3
-library expects no reply packet back from
-.Xr mmstatd 8
-for confirmation and as such, a valevolent replacement would not be able to
-cause unexpected results other than to close the socket or not accept packets.
-.El
-.Sh CONFIGURATION
-This in no way aims to replace an apache manual, obviously. However, some
-basics are necessary for
-.Nm
-to be used successfully:
-.Bl -tag -width indent -offset indent
-.It An mmstatd server should be running
-This may be any
-.Xr mmstatd 8
-running copy, since the application is told which configuration file to use
-to access it.
-.It The expected logline format
-.Nm
-expects a specific logline format which apache can be configured to generate.
-Here consists of the apache-specific format:
-.Bd -literal
-# VHost RemoteAddr UserAgent Referer BytesSent RequestMethod Request Status
-LogFormat "%v|%a|%{Referer}i|%{User-Agent}i|%B|%m|%U|%>s" apache-mmstat
-.Ed
-.It How to feed the application with apache
-Here is a general global configuration which an administrator may use to
-record verbose statistics (global and on all virtual hosts):
-.Bd -literal
-CustomLog "| /usr/local/libexec/apache-mmstat www www,mmstat /etc/mmstatd.conf GVAF" apache-mmstat
-.Ed
-.Pp
-Another use would be to run it for a local user who runs his own
-.Xr mmstatd 8 :
-.Bd -literal
-CustomLog "| /usr/local/libexec/apache-mmstat mmondor users /home/users/mmondor/root/etc/mmstatd.conf VAF" apache-mmstat
-.Ed
-.Pp
-This would ensure to change the real and effective user IDs to 'mmondor' user,
-set the groups as mmondor's primary group, 'users' and to use his own
-.Xr mmstatd.conf 5 ,
- '/home/users/mmondor/root/etc/mmstatd.conf', which for instance may specify
-to use the '/home/users/mmondor/root/var/mmstatd/mmstatd_log.sock' socket.
-.El
-.Sh AUTHOR
-apache-mmstatd was written by Matthew Mondor.
-.Sh SEE ALSO
-.Xr httpd 8 ,
-.Xr mmstat 3 ,
-.Xr mmstatd 8 .
diff --git a/mmsoftware/apache-mmstat/apache-mmstat.c b/mmsoftware/apache-mmstat/apache-mmstat.c
deleted file mode 100644 (file)
index 40b2979..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-/* $Id: apache-mmstat.c,v 1.4 2004/09/28 20:59:11 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <sys/types.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <syslog.h>
-#include <signal.h>
-
-#include <mmtypes.h>
-#include <mmreadcfg.h> /* Only used for user/group related functions */
-#include <mmstring.h>
-#include <mmstat.h>
-
-
-
-#define LINESIZ 4096
-
-
-
-int            main(int, char **);
-
-static void    log_parse(mmstat_t *, char *);
-static void    sighandler(int);
-
-
-
-/* Our list of command line arguments */
-enum argline {
-    ARG_COMMAND = 0,
-    ARG_USER,
-    ARG_GROUPS,
-    ARG_CONF,
-    ARG_OPTIONS,
-    ARG_MAX
-};
-
-/* Logline columns which we expect */
-enum logline {
-    COL_VHOST = 0,
-    COL_REMOTEADDR,
-    COL_REFERER,
-    COL_USERAGENT,
-    COL_BYTES,
-    COL_METHOD,
-    COL_REQUEST,
-    COL_STATUS,
-    COL_MAX
-};
-
-
-
-/* Globals */
-static bool LOG_GLOBAL;                /* G */
-static bool LOG_VHOST;         /* V */
-static bool LOG_REFERER;       /* R */
-static bool LOG_USERAGENT;     /* U */
-static bool LOG_REMOTEADDR;    /* A */
-static bool LOG_REQUEST;       /* F */
-
-
-
-int
-main(int argc, char **argv)
-{
-    char               *linebuf;
-    mmstat_t           mms;
-    struct sigaction   act;
-
-    /* Setup a signal handler for SIGSEGV so that we prevent core dumping if
-     * we ever crash.
-     */
-    act.sa_handler = sighandler;
-    act.sa_flags = SA_NOCLDWAIT;
-    sigemptyset(&act.sa_mask);
-    sigaction(SIGSEGV, &act, NULL);
-
-    /* We're normally started from apache, and run as the superuser. We
-     * therefore do all we can to be safe until we drop privileges... Let's
-     * first redirect unnecessary filedescriptors to /dev/null. But, keep
-     * stdin, of course, which we'll read logs from later on.
-     */
-    {
-       int     fd;
-
-       if ((fd = open("/dev/null", O_RDWR)) != -1) {
-           dup2(fd, 1);
-           dup2(fd, 2);
-           if (fd > 2)
-               close(fd);
-       }
-    }
-
-    /* Now perform sanity checking on launching mode and user supplied
-     * arguments.
-     */
-
-    /* Apache launches us as uid 0, we'll drop privileges soon however */
-    if (getuid() != 0) {
-       syslog(LOG_NOTICE, "%s: Not started as uid 0 from apache!? (uid %d)",
-               argv[ARG_COMMAND], getuid());
-       exit(EXIT_FAILURE);
-    }
-
-    /* We only accept a fixed number of arguments so that we restrict the
-     * need for getopt() and other libraries, or a more complex system when
-     * we're root.
-     */
-    if (argc != ARG_MAX) {
-       syslog(LOG_NOTICE, "%s: Started with wrong parameters",
-               argv[ARG_COMMAND]);
-       exit(EXIT_FAILURE);
-    }
-
-    /* Make sure that supplied user and group(s) are valid, and if so,
-     * drop privileges already.
-     */
-    {
-       uid_t   uid;
-       gid_t   *gids;
-       int     ngids;
-
-       if ((uid = mmgetuid(argv[ARG_USER])) == -1) {
-           syslog(LOG_NOTICE, "%s: Unknown user '%s'", argv[ARG_COMMAND],
-                   argv[ARG_USER]);
-           exit(EXIT_FAILURE);
-       }
-
-       if (!(gids = mmgetgidarray(&ngids, argv[ARG_GROUPS]))) {
-           syslog(LOG_NOTICE, "%s: One of following groups unknown: '%s'",
-                   argv[ARG_COMMAND], argv[ARG_GROUPS]);
-           exit(EXIT_FAILURE);
-       }
-
-       /* NOTE: mmdropprivs() uses setegid(2), setgid(2), setgroups(2),
-        * seteuid(2), setgid(2), and then verifies that it really changed to
-        * the expected user permissions, in order to return TRUE on success.
-        */
-       if (!mmdropprivs(uid, gids, ngids)) {
-           syslog(LOG_NOTICE, "%s: Cannot change uid and gids to safe privs",
-                   argv[ARG_COMMAND]);
-           exit(EXIT_FAILURE);
-       }
-       mmfreegidarray(gids);
-    }
-
-    /* Et voila, we're no longer the superuser. We can now proceed and
-     * perform our slave chores as mortals. First set the MMSTATCONF
-     * environment variable for mmstat(3) API to load the right configuration
-     * file. Then, call the logging function, just because we want the main
-     * loop out of main().
-     */
-    /* Log nothing by default, enable parts which were requested only. */
-    LOG_GLOBAL = LOG_VHOST = LOG_REFERER = LOG_USERAGENT = LOG_REMOTEADDR =
-       LOG_REQUEST = FALSE;
-    if (mm_strchr(argv[ARG_OPTIONS], 'G'))
-       LOG_GLOBAL = TRUE;
-    if (mm_strchr(argv[ARG_OPTIONS], 'V'))
-       LOG_VHOST = TRUE;
-    if (mm_strchr(argv[ARG_OPTIONS], 'R'))
-       LOG_REFERER = TRUE;
-    if (mm_strchr(argv[ARG_OPTIONS], 'U'))
-       LOG_USERAGENT = TRUE;
-    if (mm_strchr(argv[ARG_OPTIONS], 'A'))
-       LOG_REMOTEADDR = TRUE;
-    if (mm_strchr(argv[ARG_OPTIONS], 'F'))
-       LOG_REQUEST = TRUE;
-
-    if (setenv("MMSTATCONF", argv[ARG_CONF], TRUE) != 0) {
-       syslog(LOG_NOTICE, "%s: Cannot setenv(3)", argv[ARG_COMMAND]);
-       exit(EXIT_FAILURE);
-    }
-
-    if (!mmstat_init(&mms, TRUE, TRUE)) {
-       syslog(LOG_NOTICE, "%s: Cannot initialize mmstat(3)",
-               argv[ARG_COMMAND]);
-       exit(EXIT_FAILURE);
-    }
-
-    /* We preferably don't want the line buffer to be on the stack */
-    if ((linebuf = malloc(LINESIZ)) == NULL) {
-       syslog(LOG_NOTICE, "%s: Cannot allocate line buffer",
-               argv[ARG_COMMAND]);
-       exit(EXIT_FAILURE);
-    }
-
-    log_parse(&mms, linebuf);
-
-    /* NOTREACHED */
-    exit(EXIT_SUCCESS);
-}
-
-
-/* ARGSUSED */
-static void
-sighandler(int sig)
-{
-    /* We only catch SIGSEGV with this handler, and exit normally. */
-    exit(EXIT_SUCCESS);
-}
-
-
-/* When we get called, privileges have been revoked and mmstat(3) has been
- * successfully initialized.
- */
-static void
-log_parse(mmstat_t *mms, char *line)
-{
-    char       *cols[COL_MAX + 1];
-
-    /* We'll exit if the pipe is closed by apache */
-    while (fgets(line, LINESIZ - 1, stdin) == line) {
-       size_t  len;
-       int     status;
-       char    *ptr;
-
-       status = 1;
-
-       /* Strip ending "\n". If there are none, we ignore the line as it
-        * consists of an abnormally long request which exceeds LINESIZ.
-        * It's next continueing line will then obviously not match the
-        * expected columns and will as a result also be ignored. It's
-        * unfortunate that fgets(3) cannot report that the line was not
-        * terminated in a faster way, without us having to go strip the
-        * line termination, but oh well, I don't want to use mmfd(3) for
-        * this. I would if I needed additional rate/bandwidth limits however.
-        */
-       len = mm_strlen(line);
-       if (len > 0 && line[len - 1] == '\n')
-           line[len - 1] = '\0';
-       else
-           continue;
-
-       /* Strip dangerous characters from line */
-       for (ptr = line; *ptr != '\0'; ptr++) {
-           if (*ptr < 32) {
-               status = 0;
-               break;
-           }
-           switch (*ptr) {
-           case ' ':           /* No spaces in key names */
-               *ptr = '_';
-               break;
-           case '*':           /* Considered as wildcards by mmstat(3) */
-               /* FALLTHROUGH */
-           case '?':
-               /* FALLTHROUGH */
-           case '%':           /* Why not, we use stdarg(3) alot */
-               *ptr = '$';
-               break;
-           }
-       }
-       if (status == 0)
-           continue;
-
-       /* Now separate line in columns and verify if the number of columns
-        * is the expected one. If it's not, ignore it.
-        */
-       if (mm_strspl(cols, line, COL_MAX, '|') != COL_MAX)
-           continue;
-
-       /* Verify that status is valid, it consists of the last field. If
-        * a malformed request or a user-supplied entry containing '|' was
-        * present, this would simply ignore the line, the correct behavior.
-        */
-       if ((status = atoi(cols[COL_STATUS])) == 0)
-           continue;
-
-       /* Start an mmstat(3) transaction, which makes sure that everything
-        * be processed atomically. This also is the recovery unit.
-        * Using a transaction is not a requirement for atomicity in this
-        * case, but it's more efficient than performing each operation
-        * independantly, beleive it or not (only one I/O syscall required).
-        */
-       mmstat_transact(mms, TRUE);
-
-       if (LOG_GLOBAL)
-           mmstat(mms, STAT_UPDATE, 1, "apache|total|requests");
-
-       switch (status) {
-       case 200:       /* Success */
-           {
-               long    bytes;
-
-               bytes = atol(cols[COL_BYTES]);
-
-               if (LOG_GLOBAL)
-                   mmstat(mms, STAT_UPDATE, bytes, "apache|total|bytes");
-               if (LOG_VHOST) {
-                   mmstat(mms, STAT_UPDATE, 1, "apache|vhost|%s|requests",
-                           cols[COL_VHOST]);
-                   mmstat(mms, STAT_UPDATE, bytes, "apache|vhost|%s|bytes",
-                           cols[COL_VHOST]);
-                   if (LOG_REQUEST)
-                       mmstat(mms, STAT_UPDATE, 1, "apache|vhost|%s|%s|%s",
-                               cols[COL_VHOST], cols[COL_METHOD],
-                               cols[COL_REQUEST]);
-                   if (LOG_REFERER)
-                       mmstat(mms, STAT_UPDATE, 1,
-                               "apache|vhost|%s|referer|%s", cols[COL_VHOST],
-                               cols[COL_REFERER]);
-                   if (LOG_USERAGENT)
-                       mmstat(mms, STAT_UPDATE, 1, "apache|vhost|%s|agent|%s",
-                               cols[COL_VHOST], cols[COL_USERAGENT]);
-               }
-           }
-           break;
-       case 404:       /* Not found */
-           if (LOG_GLOBAL)
-               mmstat(mms, STAT_UPDATE, 1, "apache|total|errors");
-           if (LOG_VHOST) {
-               mmstat(mms, STAT_UPDATE, 1, "apache|vhost|%s|errors",
-                       cols[COL_VHOST]);
-               if (LOG_REFERER)
-                   mmstat(mms, STAT_UPDATE, 1, "apache|vhost|%s|referer|%s",
-                           cols[COL_VHOST], cols[COL_REFERER]);
-               if (LOG_USERAGENT)
-                   mmstat(mms, STAT_UPDATE, 1, "apache|vhost|%s|agent|%s",
-                           cols[COL_VHOST], cols[COL_USERAGENT]);
-           }
-           break;
-       case 400:       /* Bad request */
-           if (LOG_GLOBAL)
-               mmstat(mms, STAT_UPDATE, 1, "apache|total|errors");
-           if (LOG_VHOST) {
-               if (LOG_REFERER)
-                   mmstat(mms, STAT_UPDATE, 1, "apache|vhost|%s|referer|%s",
-                           cols[COL_VHOST], cols[COL_REFERER]);
-               if (LOG_USERAGENT)
-                   mmstat(mms, STAT_UPDATE, 1, "apache|vhost|agent|%s",
-                           cols[COL_VHOST], cols[COL_USERAGENT]);
-           }
-           break;
-       case 403:       /* Denied */
-           if (LOG_GLOBAL) {
-               mmstat(mms, STAT_UPDATE, 1, "apache|total|denied");
-               if (LOG_REMOTEADDR)
-                   mmstat(mms, STAT_UPDATE, 1, "apache|denied|%s",
-                           cols[COL_REMOTEADDR]);
-           }
-           if (LOG_VHOST) {
-               mmstat(mms, STAT_UPDATE, 1, "apache|vhost|%s|denied",
-                       cols[COL_VHOST]);
-               if (LOG_REMOTEADDR)
-                   mmstat(mms, STAT_UPDATE, 1, "apache|vhost|%s|denied|%s",
-                           cols[COL_VHOST], cols[COL_REMOTEADDR]);
-               if (LOG_REFERER)
-                   mmstat(mms, STAT_UPDATE, 1, "apache|vhost|%s|referer|%s",
-                           cols[COL_VHOST], cols[COL_REFERER]);
-               if (LOG_USERAGENT)
-                   mmstat(mms, STAT_UPDATE, 1, "apache|vhost|%s|agent|%s",
-                           cols[COL_VHOST], cols[COL_USERAGENT]);
-           }
-           break;
-       }
-
-       /* Close transaction, that is, commit any changes. Once this is
-        * called, the statistics are relayed to the mmstat(8) daemon.
-        */
-       if (!mmstat_transact(mms, FALSE))
-           syslog(LOG_NOTICE, "mmstat error - %s", strerror(errno));
-    }
-}
diff --git a/mmsoftware/apache-mmstat/makepart.sh b/mmsoftware/apache-mmstat/makepart.sh
deleted file mode 100755 (executable)
index 1b53154..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-# $Id: makepart.sh,v 1.1 2003/07/02 17:20:55 mmondor Exp $
-
-. ../mmlib/makedefs.sh
-
-OBJS='apache-mmstat.o'
-BIN1='apache-mmstat'
-
-if [ "$1" = "clean" ]; then
-       show $RM $OBJS $BIN1
-       exit 0
-fi
-
-INCDIR="-I../mmlib $STDINC"
-LIBDIR="$STDLIB"
-LIBS='../mmlib/libmmondor.a -lc'
-
-for obj in $OBJS; do
-       if [ ! -f $obj ]; then
-               src=`$ECHO $obj | $SED 's/\.o$/.c/'`
-               show $CC $CFLAGS -c $INCDIR $src
-       fi
-done
-
-show $CC $CFLAGS -o $BIN1 $INCDIR $LIBDIR $BIN1.o $LIBS
diff --git a/mmsoftware/bot/Makefile b/mmsoftware/bot/Makefile
deleted file mode 100644 (file)
index d4c6585..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-# $Id: Makefile,v 1.2 2003/01/01 14:54:10 mmondor Exp $
-
-CC = gcc
-MAKE = make
-#STRIP = strip
-
-CFLAGS += -D_REENTRANT -Wall
-
-INCDIR = -I../mmlib -I/usr/include -I/usr/pkg/include
-LIBDIR = -L/usr/local/lib -L/usr/lib -L/lib -L/usr/pkg/lib
-
-LIBS = ../mmlib/libmmondor.a -lc
-
-OBJS = zenbot.o
-
-
-
-CCOBJ = $(CC) $(CFLAGS) -c $(INCDIR)
-
-
-
-
-zenbot: $(OBJS)
-       $(CC) $(CFLAGS) -o zenbot $(INCDIR) $(LIBDIR) $(OBJS) $(LIBS)
-#      $(STRIP) -s zenbot
-
-
-
-
-clean:
-       -rm -f $(OBJS) zenbot
-
-
-zenbot.o:
-       $(CCOBJ) zenbot.c
-
diff --git a/mmsoftware/bot/irc.txt b/mmsoftware/bot/irc.txt
deleted file mode 100644 (file)
index 359b9ec..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-:<nick>!<ident>@<host> <command> ... :<text>
-":*!*@* * *"           rest depends on command
-
-:nanobit!identz@205.205.36.96 JOIN :#xlnx
-:Isky!~jorwyn@216.255.216.37 PRIVMSG #xlnx :it turns out Arizona wouldn't ...
-:phad_!mmondor@ppp3.arobas.net PRIVMSG nanobit :sup
-:phad_!mmondor@ppp3.arobas.net KICK #linux nanobit :because.
-
-
-
-:<server> <command> ... :<text>
-":* * *"
-
-:irc.gobot.ca NOTICE nanobit :*** Notice -- motd was last changed at
-
-
-
-:<server> <code> ...                                   ":
-":* ??? *"             rest depends on code
-
-:irc.gobot.ca 001 nanobit :Welcome to Rubiks IRC nanobit!nanobit@192.168.1.4
-:irc.gobot.ca 002 nanobit :Your host is irc.gobot.ca[@0.0.0.0], running version bahamut(rubiks)-4.2(01)
-:irc.gobot.ca 003 nanobit :This server was created Tue Oct 9 2001 at 01:53:06 EDT
-:irc.gobot.ca 004 nanobit irc.gobot.ca bahamut(rubiks)-4.2(01) oiwscrknfydaAbghe biklmnoprRstvc
-:irc.gobot.ca 005 nanobit NOQUIT WATCH=128 SAFELIST LITH_HOSTMASK SAJOIN :are available on this server
-:irc.gobot.ca 251 nanobit :There are 1 users and 0 invisible on 1 servers
-:irc.gobot.ca 255 nanobit :I have 1 clients and 0 servers
-:irc.gobot.ca 265 nanobit :Current local users: 1 Max: 2
-:irc.gobot.ca 266 nanobit :Current global users: 1 Max: 2
-:irc.gobot.ca 422 nanobit :MOTD File is missing
-:irc.gobot.ca 353 nanobit = #netbsd :nanobit 
-:irc.gobot.ca 366 nanobit #netbsd :End of /NAMES list.
-:twisted.ma.us.dal.net 332 nanobit #xlnx :Welcome to #xlnx. | Don't be a dick. | IceWM is for jblack lovers. | EAT SCRYE'S ASS | <Isky> scrye: I wanted to play with you guys
-:twisted.ma.us.dal.net 333 nanobit #xlnx simoriah 1026932695
-:twisted.ma.us.dal.net 353 nanobit @ #xlnx :nanobit uidzero gxx dalej snL20 Isky phad lucca PFY bylzz Dralock Zalamander emann kerx Traktopel OpenSorceror deegan slaker Psi-Jack @simoriah Scrye gezr malkodan Magnus-swe adefa zemo ananke
-:twisted.ma.us.dal.net 366 nanobit #xlnx :End of /NAMES list.
-
-
-
-PING :<server>
-"PING :*"
-
-PING :twisted.ma.us.dal.net
-
-
-
-In interesting way to protect a channel would be having several bots from
-several hosts connect to various ircd on a single network, and joining to
-a common channel (the first bot joining would make sure to set the invisible
-flag to make sure that users do not see which one it is using /whois).
-
-They then would use that channel for synchronization. When a bot on the other
-channel requires op status, it would consult the list of users on the hidden
-channel and try to locate in the wanted channel a common one with op status.
-It would then message that bot with appropriate passphrase for the bot with
-required status to op the requesting bot. If the bot could not obtain status,
-it will try again using another bot on the channel.
-
-The same technique could be used to distribute the load of security enforcing
-commands among the bots. A single bot for instance could be there to detect
-flood and/or spam anonymously, and communicate to a random bot a command
-which should be performed to clean up. Possibly the channel public messages
-could be used with read/write throtling so that a request be sent to all
-bots, the first one getting it would notice the others that it has it,
-and so would somewhat issue a lock for others to not handle it... Because
-of possible server desynch I am not sure this would be a viable method.
-Distributing actions among the bots would allow a quite large number of
-flooding hosts to be banned and kicked out, without causing a single
-client to be considered flooding by the server, services or other bots.
-
-Operators of the channel would be able to use another passphrase and request
-op status from any currently opped bot on the channel, and possibly also
-to defer some channel actions to them.
-
-
-
-
-
-
-After a login, with user and nick, I must wait for those:
-:NickServ!service@dal.net NOTICE BritishX :This nick is owned by someone
-else.
-If those arise, I must register using PRIVMSG NickServ :identify <password>
-and then wait for a:
-:NickServ!service@dal.net NOTICE BritishX :Password accepted for BritishX.
-
-Then I may join the wanted channels.
-
-
-after nick:
-:lineone.uk.eu.dal.net 372 _Other1_ :- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-...
-:lineone.uk.eu.dal.net 376 _Other1_ :End of /MOTD command.
-:lineone.uk.eu.dal.net NOTICE _Other1_ :*** Notice -- This server runs an
-...
-:_Other1_ MODE _Other1_ :+i
-
-
-after join:
-:lineone.uk.eu.dal.net 353 _Other1_ * #linux :_Other1_ tallship Travis|H
-labrado
-:lineone.uk.eu.dal.net 366 _Other1_ #linux :End of /NAMES list.
-
-messages:
-:BYellZBub!NatRouter@c575326-a.elnsng1.mi.home.com PRIVMSG #Linux :heh, it's
-jus
-:GenericBoy!punck@dap06-158142.cora.sgi.net PRIVMSG #linux :norculf: after
-david
-:mEYoW-x!iqxbnd@co512570-a.nimc1.on.home.com PRIVMSG #Linux :*** KMail got
-signa
-:drummer^!fathafaxxa@202.9.69.138 JOIN :#linux
-:The_Hound!popeye@64-39-0-40.dhcp.hq.rackspace.com PRIVMSG #linux :TheInsanity :
-:drummer^!fathafaxxa@202.9.69.138 NICK :|sQUaLL|
-:rttrtrtrrw!ttrtrrtrat@cs27113-208.houston.rr.com NICK :linux_dumbo
-:Scrye!~scrye@sparcie.dynup.net JOIN :#linux
-:gezr!~gezr@max01-bt-14.bt.anc.net PRIVMSG #linux :Scrye !
-:The_Hound!popeye@64-39-0-40.dhcp.hq.rackspace.com PRIVMSG #linux :Scrye !
-:kimo_sabe!nick@cx331430-a.tucson1.az.home.com PRIVMSG #linux :linux_dumbo:
-noth
-:M1ck!mick@1Cust72.tnt7.sfo3.da.uu.net PART #linux
-:_Other1_!jomuzyn@1Cust85.tnt6.montreal.qb.da.uu.net PRIVMSG _Other1_ :Test
-:The_Hound!popeye@64-39-0-40.dhcp.hq.rackspace.com KICK #Linux BYellZBub
-:autoki
-:ChanServ!service@dal.net MODE #linux +b *!*@64.182.28.*
-:ChanServ!service@dal.net KICK #linux LoLos17 :User has been banned from the
-cha
-:slak_!poo@DIGI151.GRUNDY.NETSCOPE.NET JOIN :#linux
-:kimo_sabe!nick@cx331430-a.tucson1.az.home.com PRIVMSG #linux :QuaCka: what?
-:icak!2x@bpp-117.mega.net.id PART #linux
-:MoX12!fower@ppp13750.qc.bellglobal.com PRIVMSG _Other1_ :2,4 ya tu du monde
-:Guest60775!__________@bha4-s10.mtl.colba.net PRIVMSG #montreal :charmant21?????
-:Frankiez`!funky@202.54.122.202 QUIT :Ping timeout
-:gezr!~gezr@max01-bt-14.bt.anc.net PRIVMSG #linux :take care GenericBoy
-:GenericBoy!punck@dap06-158142.cora.sgi.net QUIT :Quit: [x]chat
-
-wall:
-:Martinos!uhu@1Cust85.tnt6.montreal.qb.da.uu.net NOTICE LrdBritish :BX-Wal#tantris] hello m/l[
-
-:sLrdBritih!oqysuma@2Cust105.tnt6.montreal.qb.da.uu.net INVITE _Other1_ :#esoterism
-
-
-
-
-
-350$ Simulateur d'ampli de guitare
-POD
-
-
-
-#Montreal: JOIN seb23!Absolom@modemcable114.90-200-24.mtl.mc.videotron.net
-#?: NICK seb23!Absolom@modemcable114.90-200-24.mtl.mc.videotron.net = Absolom
-montreal :y'a tu des gars qui veule parler avec une fille de 13 ans: fille_cool!blabla@ppp8900.qc.bellglobal.com: montreal :y'a tu des gars qui veule parler avec une fille de 13 ans
-#?: QUIT samia1!~aa@194.204.206.216 (Read error: Connection reset by peer)
-montreal :Suck it bitch: N9thMareZ!~get@qc-mon-pel-ap3-03-15.look.ca: montreal :Suck it bitch
-montreal: PART jenval!toby2@ts1-189.f1232.quebectel.com
-montreal :tina viens ma fermer ;): N9thMareZ!~get@qc-mon-pel-ap3-03-15.look.ca: montreal :tina viens ma fermer ;)
-MOTD: ogDump1_ :- *** This is the short motd ***
-NAMES: ogDump1_ = #Montreal :LogDump1_ Guest84486 beaubrun_sensuel Re[A]l_Sli[M]
-
-
-
-#?: QUIT sim27!allo@modemcable170.117-201-24.mtl.mc.videotron.net (Quit: Leaving)
-#montreal: PART belle_fille14!katymilou@ppp13552.qc.bellglobal.com
-#montreal: JOIN [[tina]]!POWER@HSE-Montreal-ppp141376.sympatico.ca
-NAMES: LogDump1_ = #Montreal :BnK BananaSplit- girl__15 lol1ta123
-^^conQueror^^
-Neodraxx PRINCE_FRANCISCO_DELAHOYA Eric-24 obskurit DarkElfes froster
-[PaRtIii]
-cyn13 lscurite fille14 seb22 La_Fille_De_Bouch_Trop_Bronzer KroniKK adtz
-andy
-
-MOTD: LogDump1_ :-
-MOTD: LogDump1_ :- Help & Information:
-MOTD: LogDump1_ :-
-MOTD: LogDump1_ :-  DALnet                  http://www.dal.net
-
-DCC SEND C:\WINDOWS\LIFE_STAGES.TXT.SHS 2506328647 4705 39936: marie-h34!terre@spc-isp-mtl-58-4-324.sprint.ca: LogDump1_ :DCC SEND C:\WINDOWS\LIFE_STAGES.TXT.SHS 2506328647 4705 39936LogDump1_ :
-
-
-TOPIC changes, NETSPLITS
-
-
-LogDump_: NOTICE FROM NickServ!service@dal.net: This nick is owned by
-someone el
-
-
-
-whois LogDump_
-:sodre.nj.us.dal.net 311 testing1_ LogDump_ ejelyb
-1Cust167.tnt5.montreal.qb.da.uu.net * :LogDump_
-:sodre.nj.us.dal.net 319 testing1_ LogDump_ :#sexe++ #Tantrism #Teleportation #Esoterism
-:sodre.nj.us.dal.net 312 testing1_ LogDump_ splitrock.tx.us.dal.net
-:Splitrock Internet Services www.splitrock.net
-:sodre.nj.us.dal.net 307 testing1_ LogDump_ :has identified for this nick
-:sodre.nj.us.dal.net 318 testing1_ LogDump_ :End of /WHOIS list.
-
-
-
-
-
-
-
-
-
-
-:splitrock.tx.us.dal.net NOTICE AUTH :*** Looking up your hostname...
-:splitrock.tx.us.dal.net NOTICE AUTH :*** Checking Ident
-:splitrock.tx.us.dal.net NOTICE AUTH :*** Found your hostname
-:splitrock.tx.us.dal.net NOTICE AUTH :*** Got Ident response
-user me me me logdump_
-nick logdump_
-:splitrock.tx.us.dal.net 001 logdump_ :Welcome to the DALnet IRC Network logdump_!iravovuf@205.205.36.84
-:splitrock.tx.us.dal.net 002 logdump_ :Your host is splitrock.tx.us.dal.net[@0.0.0.0], running version bahamut(pelennor)-1.4(08)
-:splitrock.tx.us.dal.net 003 logdump_ :This server was created Sat Nov 18 2000 at 11:14:28 CST
-:splitrock.tx.us.dal.net 004 logdump_ splitrock.tx.us.dal.net bahamut(pelennor)-1.4(08) oiwscrknfydaAbghe biklmnoprRstvc
-:splitrock.tx.us.dal.net 005 logdump_ NOQUIT WATCH=128 SAFELIST :are available on this server
-:splitrock.tx.us.dal.net 251 logdump_ :There are 2418 users and 51902 invisible on 21 servers
-:splitrock.tx.us.dal.net 252 logdump_ 54 :IRC Operators online
-:splitrock.tx.us.dal.net 254 logdump_ 18765 :channels formed
-:splitrock.tx.us.dal.net 255 logdump_ :I have 5604 clients and 1 servers
-:splitrock.tx.us.dal.net 265 logdump_ :Current local users: 5604 Max: 6014
-:splitrock.tx.us.dal.net 266 logdump_ :Current global users: 54320 Max: 80132
-:splitrock.tx.us.dal.net NOTICE logdump_ :*** Notice -- motd was last changed at 20/12/2000 4:05
-:splitrock.tx.us.dal.net NOTICE logdump_ :*** Notice -- Please read the motd if you haven't read it
-:splitrock.tx.us.dal.net 375 logdump_ :- splitrock.tx.us.dal.net Message of the Day -
-:splitrock.tx.us.dal.net 372 logdump_ :- *** This is the short motd ***
-:splitrock.tx.us.dal.net 376 logdump_ :End of /MOTD command.
-:splitrock.tx.us.dal.net NOTICE logdump_ :*** Notice -- This server runs an open proxy/wingate detection monitor.
-:splitrock.tx.us.dal.net NOTICE logdump_ :*** Notice -- If you see a port 1080 or port 23 connection from proxy3.monitor.dal.net
-:splitrock.tx.us.dal.net NOTICE logdump_ :*** Notice -- please disregard it, as it is the detector in action.
-:splitrock.tx.us.dal.net NOTICE logdump_ :*** Notice -- For more information please see http://kline.dal.net/proxy/wingate.htm
-:logdump_ MODE logdump_ :+i
-quit
-ERROR :Closing Link: 205.205.36.84 (Quit: logdump_)
-
-
-
-
-:NickServ!service@dal.net NOTICE LrdBritish :This nick is owned by someone else. Please choose another.
-:NickServ!service@dal.net NOTICE LrdBritish :If this is your nick, type: /msg NickServ@services.dal.net IDENTIFY <password>
-:NickServ!service@dal.net NOTICE LrdBritish :Your nick will be changed in 60 seconds if you do not comply. nickserv :identify mypassword
-:NickServ!service@dal.net NOTICE LrdBritish :Password accepted for \ 2LrdBritish\ 2.:MemoServ!service@dal.net NOTICE LrdBritish :New DALnet news is available!  To read, use: /msg MemoServ@services.dal.net NEWS
-
-
-:sniper.tx.us.dal.net 433 * somenick3 :Nickname is already in use.
-
-
-
-join :#unices
-:logdump_!enyqyjaqa@ppp14.arobas.net JOIN :#unices
-:paranoia.se.eu.dal.net 353 logdump_ = #unices :logdump_ @LrdBritish
-:paranoia.se.eu.dal.net 366 logdump_ #unices :End of /NAMES list.
-mode #unices
-:paranoia.se.eu.dal.net 324 logdump_ #unices +tn
-:LrdBritish!nytu@ppp14.arobas.net MODE #unices +o logdump_
-:LrdBritish!nytu@ppp14.arobas.net MODE #unices -o logdump_
-:LrdBritish!nytu@ppp14.arobas.net PART #unices
-:LrdBritish!nytu@ppp14.arobas.net JOIN :#unices
-:LrdBritish!nytu@ppp14.arobas.net QUIT :Quit: Later
-:LrdBritish!odolov@ppp14.arobas.net NOTICE logdump_ :[\ 2BX-Wall\ 2/\ 2#unices\ 2] hey
-mode LrdBritish
-:paranoia.se.eu.dal.net 221 LrdBritish +i
-mode LrdBritish +s
-:LrdBritish MODE LrdBritish :+s
-
-
-
-silence :+<nick|pattern>
-silence :-<nick|pattern>
-silence
-
-ping :<server>
-:<server> PONG <server> :<ournick>
-whois :<nick>
-...etc...
-
-
-
-
-mode #linux b
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@*.worldonline.nl ChanServ!service@dal.net 978038953
-:splitrock.tx.us.dal.net 367 test111 #linux *!*heldonsat@*.lndn1.on.wave.home.com FAdmThiago!thiago@loki.nw.com.br 978038681
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@*.nj.dial-access.att.net ChanServ!service@dal.net 978037311
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@*.neo.rr.com ChanServ!service@dal.net 978033484
-:splitrock.tx.us.dal.net 367 test111 #linux Guest*!*@* ChanServ!service@dal.net 978031468
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@203.197.* ChanServ!service@dal.net 978029728
-:splitrock.tx.us.dal.net 367 test111 #linux *!*caldera*@* PhadThao!mad@ppp97.arobas.net 978029256
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@*.next-wave.net Psi-Jack!psi-jack@pool-63.52.169.220.dlls.grid.net 978028936
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@*.aol.com Psi-Jack!psi-jack@pool-63.52.169.220.dlls.grid.net 978028879
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@62.25.84.* PhadThao!moput@ppp97.arobas.net 978028388
-:splitrock.tx.us.dal.net 367 test111 #linux *!*ADPanko*@*.next-wave.net Psi-Jack!psi-jack@pool-63.52.169.28.dlls.grid.net 978026959
-:splitrock.tx.us.dal.net 367 test111 #linux *help*!*@* Psi-Jack!psi-jack@pool-63.52.169.28.dlls.grid.net 978026745
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@202.* ChanServ!service@dal.net 978026025
-:splitrock.tx.us.dal.net 367 test111 #linux *!*no*@140.251.* Psi-Jack!psi-jack@pool-63.52.169.28.dlls.grid.net 978025931
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@*.Denver1.Level3.net PhadThao!moput@ppp97.arobas.net 978025923
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@66.38.186.* PhadThao!moput@ppp97.arobas.net 978025908
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@*.ath.bellsouth.net PhadThao!moput@ppp97.arobas.net 978025888
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@*.dublin.iol.ie PhadThao!moput@ppp97.arobas.net 978025844
-:splitrock.tx.us.dal.net 367 test111 #linux *!*@*.cgocable.net ChanServ!service@dal.net 978025319
-:splitrock.tx.us.dal.net 367 test111 #linux *!*y0@*.macam98.ac.il Psi-Jack!psi-jack@pool-63.52.169.28.dlls.grid.net 978025229
-:splitrock.tx.us.dal.net 368 test111 #linux :End of Channel Ban List
-
-
-
-
-
-Events to process:
-
-:<server> NOTICE AUTH :*** Got Ident %
-user me me me <nick>
-nick <nick>
-
-:<server> 001 <nick> :%
-:<nick> MODE <nick> :+i
-we can then perform nickserv identification
-
-
-.....identify...
-then we can join our channels
-
-
-:<server> 353 <nick> = <chan> :<nick> <nick> <nick> etc
-add to userlist for that channel if not already existing
-
-:<nick>!<ident>@<hostname> JOIN :<channel>
-add user to channel userlist
-
-:<nick>!<ident>@<hostname> PART :<channel>
-del user from <channel> userlist
-
-:<nick>!<ident>@<hostname> QUIT :%
-del user from all channels
-
-:ChanServ!service@dal.net KICK #linux LoLos17 :User has been banned
-:<nick>!<ident>@<host> KICK <chan> <nick> :%
-del user from <chan> userlist
-
-
-
-
-:<nick>!<ident>@<hostname> MODE <channel> <mode> [<nick>]
-update user's mode in memory, or channel mode
-act if the action was performed on ourselves
-MODE #unices +o :LrdBritish
-MODE #unices +p
-MODE #unices +b :<pattern>
-
-:<nick> MODE <ournick> <mode>
-update our own user mode
-to set my own user modes: mode <ournick> <mode>
-to know our current mode: mode <ournick>
-
-also watch out for +oooo modes <nick nick nick nick>
-
-
-
-
-:<nick>!<ident>@<host> NICK :%
-update <nick> to <%> in all channels
-
-:<nick>!<ident>@<hostname> PRIVMSG <channel> :%
-consider % as a normal message sent to <channel>
-
-:<nick>!<ident>@<hostname> PRIVMSG <ournick> :%
-consider % as a private message sent to us
-
-:<nick>!<ident>@<hostname> NOTICE <channel> :%
-consider % as a notice sent to the channel
-
-:<nick>!<ident>@<hostname> NOTICE <ournick> :%
-consider % as a private notice sent to us
-
-:<nick>!<ident>@<hostname> PRIVMSG <ournick> :^APING %^A
-NOTICE <nick> :^APING <%>^A
-
-:<nick>!<ident>@<hostname> PRIVMSG <ournick> :^AVERSION^A
-NOTICE <nick> :^A<versionstring>^A
-
-:<nick>!<ident>@<host> INVITE <ournick> :<chan>
-consider an invite and act
-
-PING :<server>
-respond with PONG :<server>
-
-ERROR :Closing Link: %
-reconnect
-
-
-
-
-TODO:
-
-I need a good pattern matching function, also make sure to use a pattern
-       that does not match any valid IRC character
-
-I need a token expander function
-Setup standard tokens eg:
-       &n      our nickname
-
diff --git a/mmsoftware/bot/newbot.c b/mmsoftware/bot/newbot.c
deleted file mode 100644 (file)
index 78e9fc5..0000000
+++ /dev/null
@@ -1,1259 +0,0 @@
-/* $Id: newbot.c,v 1.10 2004/07/24 17:48:21 mmondor Exp $ */
-
-/*
- * Copyright (C) 2002-2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* XXX This is incomplete software. It will probably be converted to a
- * real IRC client with support for additionnal programming through dynamic
- * modules. It is possible that the ncurses and/or frontend(s) also be
- * implemented as modules.
- *
- * TODO:
- * - Make a new library out of the timing functions developped in mmSNGId
- *   and use them in this program.
- * - ... alot of other stuff ...
- */
-
-
-
-/* HEADERS */
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include <poll.h>
-#include <errno.h>
-
-#include <syslog.h>
-#include <time.h>
-#include <ctype.h>
-
-#include <mmreadcfg.h>
-#include <mmfd.h>
-#include <mmlist.h>
-#include <mmpool.h>
-#include <mmhash.h>
-#include <mmlog.h>
-#include <mmstring.h>
-
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: newbot.c,v 1.10 2004/07/24 17:48:21 mmondor Exp $");
-
-
-
-
-/* DEFINITIONS */
-
-/* The following tables were generated automatically using mode_table.c from
- * the same author.
- */
-/* Channel modes */
-enum chanmode_enum {
-    CMOD_U = 0,
-    CMOD_c,
-    CMOD_i,
-    CMOD_k,    /* Requires string parameter */
-    CMOD_l,    /* Requires integer parameter */
-    CMOD_m,
-    CMOD_n,
-    CMOD_p,
-    CMOD_r,
-    CMOD_s,
-    CMOD_t,
-    CMOD_O,
-    CMOD_R
-};
-
-/* User modes */
-enum usermode_enum {
-    UMOD_U = 0,
-    UMOD_a,
-    UMOD_g,
-    UMOD_i,
-    UMOD_k,
-    UMOD_n,
-    UMOD_o,
-    UMOD_s,
-    UMOD_w
-};
-
-/* Channel user modes */
-enum cusermode_enum {
-    CUMOD_U = 0,
-    CUMOD_v,
-    CUMOD_o,
-};
-
-
-struct network {
-    pnode_t node;
-    pool_t servers_pool;
-    pool_t channels_pool;
-    hashtable_t channels_table;
-    list_t servers_list;
-    fdbuf *fdb;                        /* NULL if not connected */
-    /* When running through servers to connect, and connected server. */
-    struct server *server;
-    char nick[32];             /* Our nickname on this network */
-    u_int32_t mode;            /* Our user mode on this network */
-    struct freqtable freq_nick, freq_ident, freq_host;
-};
-
-struct server {
-    pnode_t node;
-    char name[128];
-};
-
-struct channel {
-    hashnode_t node;
-    pool_t users_pool;
-    hashtable_t users_table;
-    bool joined;
-    char name[64];
-    u_int32_t mode;
-    int window;
-    /* Channel l and k mode parameters */
-    int mode_limit;
-    char mode_key[32];
-};
-
-struct user {
-    hashnode_t node;
-    char name[64];
-    u_int32_t mode;
-};
-
-struct freqtable {
-    pool_t pool;
-    hashtable_t table;
-};
-
-struct freq {
-    hashtable_t node;
-    char key[64];
-    time_t expires;
-    bool ignore;
-    unsigned long freq;
-};
-
-/* An entry in the delayed output queue XXX to replace */
-struct cron {
-    pnode_t node;
-    time_t expires;
-    char data[512];
-};
-
-/* This structure is used so that an irc line can be parsed once, for
- * various conditionals that may later on take place on the elements.
- * This structure is shared among all states and functions.
- */
-struct info {
-    fdbuf *fdb;                        /* Socket */
-    struct state *state;       /* Current state */
-    int code;                  /* Command code or -1 for text command */
-    int params;                        /* Number of extra parameters or 0 */
-    char line[512];            /* Actual IRC line we received */
-    char work[512];            /* Copy of line, split with \0s */
-    /* When appropriate, these will be set, pointing to string elements into
-     * work[].
-     */
-    char *server;
-    char *nick, *ident, *host, *command;
-    char *param[10];
-    char *text;
-    /* Add other global data here if required */
-    char nickname[64];         /* Our own nick */
-    time_t zen_last;
-    time_t ping_last, ver_last;
-};
-
-/* Defines a state handler */
-struct handler_func {
-    int handler_code;          /* Mutually exclusive with command */
-    char *handler_command;
-    void (*handler_func)(struct info *);
-};
-
-/* Defines a state */
-struct state {
-    void (*state_init)(struct info *);
-    void (*state_exit)(struct info *);
-    struct handler_func *state_handlers;
-};
-
-/* Defined states */
-#define STATE_IDENT    0
-#define STATE_MAIN     1
-
-/* Configurable options */
-#define INPUT_TIMEOUT          300
-#define FLOOD_HOST_MAX         20
-#define FLOOD_HOST_TIME                60
-#define FLOOD_HOST_IGNORE      300
-#define FLOOD_USER_MAX         10
-#define FLOOD_USER_TIME                60
-#define FLOOD_USER_IGNORE      120
-#define IGN_NOTIFY             1
-#define REJOIN_DELAY           30
-#define ALLOW_PING             1
-#define PING_RATE              10
-#define ALLOW_VER              1
-#define VER_RATE               10
-#define VER_STRING "$Id: newbot.c,v 1.10 2004/07/24 17:48:21 mmondor Exp $"
-#define ANSWER_RATE            120     /* For zenbot replies frequency */
-#define INITIAL_UMODE          "+iw"
-
-/*#define DEBUG                        1*/
-
-
-
-
-/* PROTOTYPES */
-
-int main(int, char **);
-static void main_loop(struct info *);
-static int allow_entry(pool_t *, list_t *, char *, unsigned long, int, long);
-static bool irc_match(char *, char *);
-static void irc_parse(struct info *);
-static void user_add(char *, char *);
-static struct channel *user_del(char *, char *);
-static void cron_add(int, char *, ...);
-
-static void ignore_user(struct info *);
-static void ignore_host(struct info *);
-static void ident_init(struct info *);
-static void ident_main(struct info *);
-static void main_init(struct info *);
-static void main_messaged(struct info *);
-static void main_noticed(struct info *);
-static void main_joined(struct info *);
-static void main_kicked(struct info *);
-static void main_parted(struct info *);
-static void main_quitted(struct info *);
-static void main_nick(struct info *);
-static void main_mode(struct info *);
-static void main_invited(struct info *);
-static void main_names(struct info *);
-
-static void zen_init(void);
-static char *zen(void);
-
-static bool eintr(void);
-
-
-
-/* GLOBALS */
-
-/* We keep a list of networks. For each network we also keep a list of servers,
- * and of channels we should be joining along with the window the channel
- * should be connected on. When we notice that we are not connected anymore to
- * a particular network, we reconnect using any decent server. When we notice
- * that we are not joined to a channel of a network we should have joined, we
- * attempt to join the channel. Of course, we reconnect to servers and join
- * to channels respecting a reasonable delay. Every channel has it's own
- * pool_t and hashtable_t of users.
- */
-pool_t networks_pool;
-list_t networks_list;
-pool_t servers_pool;
-list_t servers_list;
-pool_t channels_pool;
-hashtable_t channels_table;
-
-/* Various slab-buffered linked lists */
-static pool_t plusers, plhosts, plcron, plchans;
-static list_t lusers, lhosts, lcron, lchans;
-
-/* The following tables were generated automatically using mode_table.c from
- * the same author. They are used for efficieny to prevent any iteration when
- * mapping modes, indexing using tables is much faster.
- */
-/* To map chanmode enums to characters and vice-versa */
-static const char chanmode_enum_to_char[] = "UciklmnprstOR";
-static const int chanmode_char_to_enum[256] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11,
-    0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 3, 4, 5, 6, 0,
-    7, 0, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* To map usermode enums to characters and vice-versa */
-static const char usermode_enum_to_char[] = "Uagiknosw";
-static const int usermode_char_to_enum[256] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 1, 0, 0, 0, 0, 0, 2, 0, 3, 0, 4, 0, 0, 5, 6,
-    0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* To map cusermode enums to characters and vice-versa */
-static const char cusermode_enum_to_char[] = "Uvo";
-static const int cusermode_char_to_enum[256] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 
-    0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
-};
-
-/* Here consists of the states definition table. Each state has a series
- * of handler functions, which will be called when a particular pattern
- * matches (with * and ? wildcards). These functions can optionally request
- * to change state by returning another state * than the one it was provided.
- */
-static struct handler_func state_ident_handlers[] = {
-    {376, NULL, ident_main},   /* End of MOTD */
-    {422, NULL, ident_main},   /* No MOTD */
-    {0, NULL, NULL}
-};
-static struct handler_func state_main_handlers[] = {
-    {0, "PRIVMSG", main_messaged},
-    {0, "NOTICE", main_noticed},
-    {0, "KICK", main_kicked},
-    {0, "PART", main_parted},
-    {0, "JOIN", main_joined},
-    {0, "QUIT", main_quitted},
-    {0, "NICK", main_nick},
-    {0, "MODE", main_mode},
-    {0, "INVITE", main_invited},
-    {353, NULL, main_names},
-    {0, NULL, NULL}
-};
-
-/* The definitions of the states, their optional init and exit code, and
- * a pointer to their various function handlers.
- */
-static struct state states[] = {
-    {ident_init, NULL, state_ident_handlers},
-    {main_init, NULL, state_main_handlers},
-    {NULL, NULL, NULL}
-};
-
-/* Channels we should join and make sure to remain in */
-static char *channels[] = {
-    "#c",
-    NULL
-};
-
-/* Zen koans */
-static int zen_num;            /* set by zen_init() */
-static int zen_offset = 0;     /* Current quote offset */
-static char *zen_strings[] = {
-    "The cypress tree in the yard.",
-    "Many moons ago.",
-    "Eat your bowl.",
-    "A bum on the hand, is better than two in the bush.",
-    "The definition of the states.",
-    "It is.",
-    "Yes.",
-    "No.",
-    "Long sessions.",
-    "Have you finished eating? Then wash your bowl.",
-    "The butterfly is silent when the eagle walks upon the sand.",
-    "Tantamount to painting your leg red and walking the dog.",
-    "Carrots.",
-    "A guiding light at the bottom of the firepit.",
-    "A sinking boat picking up people in the middle of the sea.",
-    "You have a wooden leg, does that make you a table?",
-    "It puts the lotion on its skin or else it gets the hose again.",
-    "Watch what cooks in the oven.",
-    "When he breathes short, he knoes that he is breathing short, when he breathes deeply he also knows that he does.",
-    "What is the sound of one hand clapping?",
-    "What is your original face before your parents were born?",
-    "When the many are reduced to one, what is the one reduced to?",
-    "What is mu?",
-    "Bring out your mind here before me, and I will pacify it.",
-    "There! I have pacified your mind.",
-    "Here is a tall bamboo; there is a short one.",
-    "Three pound of flax!",
-    "Matchbox is a noise. Is this a noise?",
-    "Every natural fact is a symbol of some spiritual fact.",
-    "The highest human purpose is always to reinvent and celebrate the sacred.",
-    "People who take the time to be alone usually have depth, and quiet reserve.",
-    "Check out http://google.com, it is a very good site.",
-    "We think in generalities, but we live in details.",
-    "The oak tree in the garden.",
-    "Insects, grass and trees you must not hurt.",
-    "Cultivate the garden within.",
-    "This cabbage, these carrots, these potatoes, these onions ... will soon become me.  Such a tasty fact!",
-    "Learning how to operate a soul figures to take time.",
-    "There's nothing much, really, to say.",
-    "The Tao exists in the crickets... in the grasses... in tiles and bricks... and in shit and piss.",
-    "A garden is a private world or it is nothing.",
-    "One real world is enough.",
-    "Right here, right now.",
-    "Mu!",
-    "Before your parents gave birth to you.",
-    "Neither standing nor sitting will do, now what will you do?",
-    "What do you do?",
-    "Not relying on words or letters.",
-    "The dinner is never complete without some meat in your seat.",
-    "A clique that seeks power usually through intrigue.",
-    "NULL.",
-    "void *(void *)(void *).",
-    NULL
-};
-
-
-
-/* FUNCTIONS */
-
-static void ignore_user(struct info *data)
-{
-    if (IGN_NOTIFY) {
-       fdbprintf(data->fdb,
-                 "PRIVMSG %s :Ignoring your ident for %d seconds.\r\n",
-                 data->nick, FLOOD_USER_IGNORE);
-       /* fdbprintf(data->fdb, "WHOIS :%s\r\n", data->nick); */
-    }
-}
-
-static void ignore_host(struct info *data)
-{
-    if (IGN_NOTIFY) {
-       fdbprintf(data->fdb,
-                 "PRIVMSG %s :Ignoring your hostname for %d seconds.\r\n",
-                 data->nick, FLOOD_HOST_IGNORE);
-       /* fdbprintf(data->fdb, "WHOIS :%s\r\n", data->nick); */
-    }
-}
-
-
-static void ident_init(struct info *data)
-{
-    data->zen_last = time(NULL);
-    fdbprintf(data->fdb, "USER %s %s %s %s\r\n", data->nickname,
-             data->nickname, data->nickname, data->nickname);
-    fdbprintf(data->fdb, "NICK %s\r\n", data->nickname);
-}
-
-static void ident_main(struct info *data)
-{
-    /* Simply switch to the main state */
-    data->state = &states[STATE_MAIN];
-}
-
-
-static void main_init(struct info *data)
-{
-    int i;
-
-    /* Set our initial umode */
-    fdbprintf(data->fdb, "MODE %s :%s\r\n", data->nickname, INITIAL_UMODE);
-
-    /* Join channels */
-    for (i = 0; channels[i]; i++)
-       fdbprintf(data->fdb, "JOIN :%s\r\n", channels[i]);
-}
-
-static void main_messaged(struct info *data)
-{
-    char *str;
-    time_t t = time(NULL);
-    int r;
-
-    /* Handle PING and VERSION CTCP requests */
-    if (ALLOW_PING && !mm_strncmp(data->text, "\001PING ", 6)) {
-       long tim;
-       if (t - data->ping_last > PING_RATE) {
-           tim = atol(&data->text[6]);
-           fdbprintf(data->fdb, "NOTICE %s :\001PING %ld\001\r\n",
-                     data->nick, tim);
-           data->ping_last = t;
-       }
-       return;
-    }
-    if (ALLOW_VER && !mm_strcmp(data->text, "\001VERSION\001")) {
-       if (t - data->ver_last > VER_RATE) {
-           fdbprintf(data->fdb, "NOTICE %s :\001VERSION %s\001\r\n",
-                     data->nick, VER_STRING);
-           data->ver_last = t;
-       }
-       return;
-    }
-
-    /* Reply to user via /msg or on channel depending on origin.
-     * Also make sure to not answer too frequently.
-     */
-    if (t - data->zen_last > ANSWER_RATE) {
-       if (irc_match(data->text, "*why *") ||
-           irc_match(data->text, "*how *") ||
-           irc_match(data->text, "*who *") ||
-           irc_match(data->text, "*what *") ||
-           irc_match(data->text, "*where *") ||
-           irc_match(data->text, "*when *")) {
-           data->zen_last = t;
-           str = zen();
-           /* Let's simulate a human delay (2 - 10 secs) */
-           r = 2 + (rand() % 8);
-           if (!mm_strcmp(data->param[0], data->nickname))
-               cron_add(r, "PRIVMSG %s :%s\r\n", data->nick, str);
-           else
-               cron_add(r, "PRIVMSG %s :%s: %s\r\n", data->param[0],
-                        data->nick, str);
-       }
-    }
-}
-
-static void main_noticed(struct info *data)
-{
-    /* XXX */
-}
-
-static void main_joined(struct info *data)
-{
-    struct channel *ch;
-
-    /* data->text consists of channel name, data->nick of nickname */
-    if (!mm_strcmp(data->nick, data->nickname)) {
-       /* We have joined a new channel, create new channel node with it's
-        * users list
-        */
-       if ((ch = (struct channel *)pool_alloc(&plchans, TRUE))) {
-           if (pool_init(&ch->pchannel_users, "pchannel_users",
-                       malloc, free, NULL, NULL, sizeof(struct user),
-                       4096 / sizeof(struct user), 0, 0)) {
-               DLIST_INIT(&ch->channel_users);
-               ch->channel_hash = mm_strhash64(data->text);
-               mm_strcpy(ch->channel_name, data->text);
-               DLIST_APPEND(&lchans, (node_t *)ch);
-           }
-       }
-    } else {
-       /* Another user joined one of the channels we are in, update
-        * corresponding channel's userlist
-        */
-       user_add(data->text, data->nick);
-    }
-}
-
-static void main_kicked(struct info *data)
-{
-    struct channel *ch;
-
-    /* data->param[0] consists of channel name, data->param[1] of nick */
-    ch = user_del(data->param[0], data->param[1]);
-    if (!mm_strcmp(data->param[1], data->nickname)) {
-       /* We have been kicked out of the channel, free all channel
-        * info and send a delayed join request
-        */
-       DLIST_UNLINK(&lchans, (node_t *)ch);
-       pool_destroy(&ch->pchannel_users);
-       pool_free((pnode_t *)ch);
-       cron_add(REJOIN_DELAY, "JOIN :%s\r\n", data->param[0]);
-    }
-}
-
-static void main_parted(struct info *data)
-{
-    struct channel *ch;
-
-    /* data->nick consists of nickname, data->param[0] of channel name */
-    ch = user_del(data->param[0], data->nick);
-    if (!mm_strcmp(data->nick, data->nickname)) {
-       /* We have left a channel, free all channel info */
-       DLIST_UNLINK(&lchans, (node_t *)ch);
-       pool_destroy(&ch->pchannel_users);
-       pool_free((pnode_t *)ch);
-    }
-}
-
-static void main_quitted(struct info *data)
-{
-    struct channel *ch, *tmp;
-
-    user_del(NULL, data->nick);
-    if (!mm_strcmp(data->nick, data->nickname)) {
-       /* We have quitted, free all channel info */
-       ch = (struct channel *)lchans.top;
-       while (ch) {
-           tmp = (struct channel *)ch->node.node.next;
-           DLIST_UNLINK(&lchans, (node_t *)ch);
-           pool_free((pnode_t *)ch);
-           ch = tmp;
-       }
-    }
-}
-
-static void main_nick(struct info *data)
-{
-    u_int64_t hash, nhash;
-    struct channel *ch;
-    struct user *us;
-
-    /* A user changed nickname, make sure to update it in all our channels
-     * the user is in. If we are the one who changed nick, also update our
-     * internal own nickname record.
-     */
-    hash = mm_strhash64(data->nick);
-    nhash = mm_strhash64(data->text);
-
-    ch = (struct channel *)lchans.top;
-    while (ch) {
-       us = (struct user *)ch->channel_users.top;
-       while (us) {
-           if (us->user_hash == hash)
-               break;
-           us = (struct user *)us->node.node.next;
-       }
-       if (us) {
-           us->user_hash = nhash;
-           mm_strcpy(us->user_nick, data->text);
-       }
-       ch = (struct channel *)ch->node.node.next;
-    }
-    /*
-    if (!mm_strcmp(data->nick, data->nickname)) {
-       mm_strncpy(data->nickname, data->text, 63);
-       XXX Update hash also?
-    }
-    */
-}
-
-static void main_mode(struct info *data)
-{
-    /* A mode change occured for either ourself, a channel or another user.
-     * we only record those for now, but action could be taken also on certain
-     * mode change events. XXX
-     */
-    /* :PhadThai!mmondor@gobot.xisop MODE #netbsd-devel +o nanobit
-     * :nanobit MODE nanobit :+iw
-     */
-    if (data->ident && data->param[0] && *data->param[0] == '#') {
-       /* cmode or cumode change */
-    } else {
-       /* umode change */
-#ifdef DEBUG
-       printf("UMODE\n");
-#endif
-    }
-}
-
-static void main_invited(struct info *data)
-{
-    /* XXX */
-}
-
-static void main_names(struct info *data)
-{
-    char *words[64];           /* XXX check how many max */
-    int cols, i;
-
-    /* data->param[2] consists of channel name, and data->text of nicks */
-    if ((cols = mm_straspl(words, data->text, 63)) > 0) {
-       for (i = 0; i < cols; i++)
-           user_add(data->param[2], words[i]);
-    }
-}
-
-
-/* The main startup function */
-int main(int argc, char **argv)
-{
-    int port, fd;
-    char *server;
-    struct sockaddr_in client;
-    struct in_addr iaddr;
-    struct info data;
-
-    fdfuncs fdf = {
-       malloc,
-       free,
-       poll,
-       read,
-       write,
-       sleep,
-       usleep,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       eintr
-    };
-
-    if (argc != 3) {
-       printf("Usage: zenbot <nick> <ipaddress>\n");
-       exit (-1);
-    }
-
-    mm_memclr(&data, sizeof(data));
-
-    /* Parse arguments */
-    server = argv[2];
-    mm_strncpy(data.nickname, argv[1], 63);
-    port = 6667;
-
-    /* Zen setup */
-    zen_init();
-
-    if (pool_init(&plusers, "plusers", malloc, free, NULL, NULL,
-               sizeof(struct freq), 8192 / sizeof(struct freq), 0, 0)) {
-       DLIST_INIT(&lusers);
-       if (pool_init(&plhosts, "plhosts", malloc, free, NULL, NULL,
-                   sizeof(struct freq), 8192 / sizeof(struct freq), 0, 0)) {
-           DLIST_INIT(&lhosts);
-           if (pool_init(&plcron, "plcron", malloc, free, NULL, NULL,
-                       sizeof(struct cron), 8192 / sizeof(struct cron),
-                       0, 0)) {
-               DLIST_INIT(&lcron);
-               if (pool_init(&plchans, "plchans", malloc, free, NULL, NULL,
-                           sizeof(struct channel),
-                           8192 / sizeof(struct channel), 0, 0)) {
-                   DLIST_INIT(&lchans);
-                   /* Prepare our fd buffering wrapper */
-                   if ((data.fdb = fdbopen(&fdf, NULL, -1, 4096, 4096, 1024,
-                                   1024, INPUT_TIMEOUT * 1000,
-                                   INPUT_TIMEOUT * 1000, FALSE))) {
-                       /* Loop indefinitely */
-                       for (;;) {
-                           /* Connect to server */
-                           if ((fd = socket(AF_INET, SOCK_STREAM, 0)) != -1) {
-                               mm_memclr(&client, sizeof(struct sockaddr_in));
-                               if ((inet_aton(server, &iaddr))) {
-                                   client.sin_family = AF_INET;
-                                   client.sin_addr.s_addr = iaddr.s_addr;
-                                   client.sin_port = htons(port);
-                                   if ((connect(fd,
-                                           (struct sockaddr *)&client,
-                                           sizeof(struct sockaddr_in)))
-                                           != -1) {
-                                       fcntl(fd, F_SETFL, O_NONBLOCK);
-                                       fdbparam_set(data.fdb, fd, FDBP_FD);
-                                       /* Serve our purpose */
-                                       data.state = &states[STATE_IDENT];
-                                       main_loop(&data);
-                                       fdbflushr(data.fdb);
-                                       fdbflushw(data.fdb);
-                                       fdbparam_set(data.fdb, -1, FDBP_FD);
-                                   } else
-                                       sleep(30);
-                               }
-                               close(fd);
-                           }
-                       }
-                       fdbclose(data.fdb);
-                   }
-                   pool_destroy(&plchans);
-               }
-               pool_destroy(&plcron);
-           }
-           pool_destroy(&plhosts);
-       }
-       pool_destroy(&plusers);
-    }
-
-    exit(0);
-}
-
-
-/* This function consists of the main state switcher loop, and basically
- * reads lines, calling the matching function handlers for the current
- * state. When a state switch occurs, exit code of the current state is
- * executed, and init code of the new state, if any.
- * We only return if a handler function returns a NULL pointer, or if
- * we loose connection with the server.
- * We internally take care of PING replies.
- */
-static void main_loop(struct info *data)
-{
-    struct state *curstate;
-    struct handler_func *fn;
-    int i;
-
-    if (data->state->state_init)
-       data->state->state_init(data);
-
-    for (;;) {
-       struct cron *nod, *tmp;
-       time_t t;
-
-       /* Verify if any queued data has expired and should be released out.
-        * unfortunately because of the way we currently work, some IRC
-        * activity is required to trigger this. XXX Ideally the fdbgets()
-        * timeout should be set to 1 when there is queued data, and timeout
-        * should not be assumed to be a server/connection failiure. For now,
-        * this should work fine on a channel with activity, or if we are
-        * on multiple channels.
-        */
-       t = time(NULL);
-       nod = (struct cron *)lcron.top;
-       while (nod) {
-           tmp = (struct cron *)nod->node.node.next;
-           if (nod->expires < t) {
-               DLIST_UNLINK(&lcron, (node_t *)nod);
-               fdbputs(data->fdb, nod->data);
-               pool_free((pnode_t *)nod);
-           }
-           nod = tmp;
-       }
-
-       fdbflushw(data->fdb);
-
-       if ((i = fdbgets(data->fdb, data->line, 511, FALSE)) > -1) {
-
-           /* We got a line, check if there exists any handler to serve
-            * it within current state. Execute the handler if required,
-            * and perform sane state switching if requested by a handler.
-            */
-
-           if (!mm_strncmp(data->line, "PING :", 6)) {
-               /* Transform PING to PONG and reply to server */
-               data->line[1] = 'O';
-               fdbprintf(data->fdb, "%s\r\n", data->line);
-               continue;
-           }
-
-           irc_parse(data);
-
-           /* Useful for debugging */
-#ifdef DEBUG
-           fwrite("\033[1m", 4, 1, stdout);
-           fwrite(data->line, i, 1, stdout);
-           fwrite("\r\n", 2, 1, stdout);
-           fwrite("\033[0m", 4, 1, stdout);
-           fflush(stdout);
-           printf("code: %d server: '%s' nick: '%s' ident: '%s' host: '%s' command: '%s' text: '%s' params: %d ",
-                data->code, data->server, data->nick, data->ident,
-                data->host, data->command, data->text, data->params);
-           for (i = 0; i < data->params; i++)
-               printf("param[%d]: '%s' ", i, data->param[i]);
-           printf("\r\n\r\n");
-           fflush(stdout);
-#endif
-
-           if (data->code == -1 && data->ident) {
-               int res;
-               bool allow = FALSE;
-
-               /* Check against flood by ident and hostname */
-               if (!(res = allow_entry(&plhosts, &lhosts, data->host,
-                               FLOOD_HOST_MAX, FLOOD_HOST_TIME,
-                                       FLOOD_HOST_IGNORE))) {
-                   if (!(res = allow_entry(&plusers, &lusers, data->ident,
-                                   FLOOD_USER_MAX, FLOOD_USER_TIME,
-                                   FLOOD_USER_IGNORE)))
-                       allow = TRUE;
-                   else if (res == 2)
-                       ignore_user(data);
-               } else if (res == 2)
-                   ignore_host(data);
-               if (!allow)
-                   continue;
-           }
-
-           curstate = data->state;
-           fn = curstate->state_handlers;
-           while (fn->handler_func) {
-               bool allow;
-
-               allow = FALSE;
-               if (fn->handler_code && data->code != -1) {
-                   if (fn->handler_code == data->code)
-                       allow = TRUE;
-               } else if (fn->handler_command && data->command) {
-                   if (!mm_strcmp(fn->handler_command, data->command))
-                       allow = TRUE;
-               }
-               if (allow) {
-                   /* Execute handler for matching pattern */
-                   fn->handler_func(data);
-                   if (data->state != curstate) {
-                       /* Perform state switching */
-                       if (curstate->state_exit)
-                           curstate->state_exit(data);
-                       if (data->state->state_init)
-                           data->state->state_init(data);
-                   }
-                   break;
-               }
-               fn++;
-           }
-
-       } else
-           break;
-    }
-}
-
-
-/* This function is useful to easily perform flood quota checking on nicks
- * and/or hosts. Returns 0 if the entry is allowed, 1 if it is not, 2 if
- * it just started to be ignored.
- */
-static int
-allow_entry(pool_t *pool, list_t *lst, char *entry, unsigned long max,
-       int secs, long igndelay)
-{
-    u_int64_t hash = mm_strhash64(entry);
-    int ret = 0;
-    struct freq *node, *tmp;
-    time_t t = time(NULL);
-
-    /* Locate if entry exists */
-    node = (struct freq *)lst->top;
-    while (node) {
-       tmp = (struct freq *)node->node.node.next;
-       if (node->expires < t) {
-           /* Expired, drop this entry */
-           DLIST_UNLINK(lst, (node_t *)node);
-           pool_free((pnode_t *)node);
-       } else if (node->hash == hash)
-           break;
-       node = tmp;
-    }
-    if (node) {
-       /* Entry existed, increase frequency and optionally toggle ignore */
-       node->freq++;
-       if (!node->ignore) {
-           if (node->freq > max) {
-               node->ignore = TRUE;
-               node->expires += igndelay;
-               ret = 2;
-           }
-       } else
-           ret = 1;
-    } else {
-       /* Add new entry */
-       if ((node = (struct freq *)pool_alloc(pool, FALSE))) {
-           node->expires = t + secs;
-           node->ignore = FALSE;
-           node->hash = hash;
-           node->freq = 1;
-           DLIST_APPEND(lst, (node_t *)node);
-       }
-    }
-
-    return (ret);
-}
-
-
-/* This function returns weither or not pat matches string.
- * We only perform simple * and ? pattern matching, case-sensitive.
- */
-static bool irc_match(char *str, char *pat)
-{
-    while (*pat ^ '*') {
-       if (!*str) {
-           if (*pat)
-               return (FALSE);
-           else
-               return (TRUE);
-       }
-       if (*str ^ *pat && *pat ^ '?')
-           return (FALSE);
-       pat++;
-       str++;
-    }
-
-    while (pat[1] == '*')
-       pat++;
-
-    do {
-       if (irc_match(str, pat + 1))
-           return (TRUE);
-    } while (*str++);
-
-    return (FALSE);
-}
-
-
-/* Some mmondor-style string parsing magic, fill data fields according to
- * IRC protocol line
- */
-static void irc_parse(struct info *data)
-{
-    char *ptr, *optr, *words[16];
-    size_t cols;
-    int i, i2;
-
-    /* Init, everything set to NULL, and code to -1 by default */
-    mm_strcpy(data->work, data->line);
-    ptr = data->work;
-    data->code = -1;
-    data->params = 0;
-    data->server = data->nick = data->ident = data->host = data->command =
-       data->text = NULL;
-
-    if (*ptr == ':') {
-       /* IRC lines start with ':' */
-       ptr++;
-       optr = ptr;
-       while (*ptr != '\0' && *ptr != ':')
-           ptr++;
-       if (*ptr == ':') {
-           /* Multiword text field */
-           *ptr++ = '\0';
-           data->text = ptr;
-       }
-       if ((cols = mm_straspl(words, optr, 16)) > 1) {
-           /* Determine the type of IRC protocol line and fill corresponding
-            * pointers.
-            */
-           if ((i = atoi(words[1]))) {
-               /* Code based line */
-               data->server = *words;
-               data->code = i;
-           } else {
-               /* Text command based line */
-               ptr = *words;
-               while (*ptr != '\0' && *ptr != '.' && *ptr != '!')
-                   ptr++;
-               if (*ptr == '.')
-                   /* Server name in first column */
-                   data->server = *words;
-               else {
-                   /* Nickname in first column, optional ident and host */
-                   ptr = data->nick = *words;
-                   while (*ptr != '\0' && *ptr != '!')
-                       ptr++;
-                   if (*ptr == '!') {
-                       *ptr++ = '\0';
-                       data->ident = ptr;
-                       while (*ptr != '\0' && *ptr != '@')
-                           ptr++;
-                       if (*ptr == '@') {
-                           *ptr++ = '\0';
-                           data->host = ptr;
-                       }
-                   }
-               }
-               data->command = words[1];
-           }
-           if (cols > 2) {
-               /* Additional parameters before text */
-               i = 0;
-               for (i2 = 2; i2 < cols; i2++)
-                   data->param[i++] = words[i2];
-               data->params = i;
-           }
-       }
-    }
-}
-
-
-/* Adds a user to a channel, also checks for @ and + in start of nick to
- * set according mode.
- */
-static void user_add(char *chan, char *nick)
-{
-    u_int64_t chanhash, nickhash;
-    struct channel *ch;
-    struct user *us;
-    int mode;
-
-    mm_strlower(chan);
-    chanhash = mm_strhash64(chan);
-
-    mode = 0;
-    if (*nick) {
-       if (*nick == '@') {
-           mode |= (1L << 0);
-           nick++;
-       } else if (*nick == '+') {
-           mode |= (1L << 1);
-           nick++;
-       }
-    }
-    nickhash = mm_strhash64(nick);
-
-    /* Find channel user should be added to */
-    ch = (struct channel *)lchans.top;
-    while (ch) {
-       if (ch->channel_hash == chanhash)
-           break;
-       ch = (struct channel *)ch->node.node.next;
-    }
-    if (ch) {
-       /* We found channel */
-       if ((us = (struct user *)pool_alloc(&ch->pchannel_users, FALSE))) {
-           mm_strcpy(us->user_nick, nick);
-           us->user_hash = nickhash;
-           us->user_mode = mode;
-#ifdef DEBUG
-           printf("ADDED USER '%s' TO CHANNEL '%s'\n", nick, chan);
-#endif
-           DLIST_APPEND(&ch->channel_users, (node_t *)us);
-       }
-    }
-}
-
-
-/* Deletes a nick from specified channel, or from all channels if chan is NULL
- */
-static struct channel *user_del(char *chan, char *nick)
-{
-    u_int64_t chanhash, nickhash;
-    struct channel *ch;
-    struct user *us;
-
-    nickhash = mm_strhash64(nick);
-    ch = NULL;
-
-    if (chan) {
-       /* Delete user on specified channel */
-       mm_strlower(chan);
-       chanhash = mm_strhash64(chan);
-       ch = (struct channel *)lchans.top;
-       while (ch) {
-           if (ch->channel_hash == chanhash)
-               break;
-           ch = (struct channel *)ch->node.node.next;
-       }
-       if (ch) {
-           /* We found channel */
-           us = (struct user *)ch->channel_users.top;
-           while (us) {
-               if (us->user_hash == nickhash)
-                   break;
-               us = (struct user *)us->node.node.next;
-           }
-           if (us) {
-               /* We found nick */
-               DLIST_UNLINK(&ch->channel_users, (node_t *)us);
-               pool_free((pnode_t *)us);
-#ifdef DEBUG
-               printf("DELETED USER '%s' FROM CHANNEL '%s'\n", nick,
-                      chan);
-#endif
-           }
-       }
-    } else {
-       /* Delete user on all channels */
-       ch = (struct channel *)lchans.top;
-       while (ch) {
-           us = (struct user *)ch->channel_users.top;
-           while (us) {
-               if (us->user_hash == nickhash) {
-                   DLIST_UNLINK(&ch->channel_users, (node_t *)us);
-                   pool_free((pnode_t *)us);
-                   break;
-               }
-               us = (struct user *)us->node.node.next;
-           }
-           ch = (struct channel *)ch->node.node.next;
-       }
-#ifdef DEBUG
-       printf("DELETED USER '%s' FROM ALL CHANNELS\n", nick);
-#endif
-    }
-
-    return (ch);
-}
-
-
-/* Allows to queue data to be sent after a certain delay has been observed. */
-static void cron_add(int secs, char *fmt, ...)
-{
-    struct cron *nod;
-    time_t t = time(NULL);
-    va_list arg_ptr;
-
-    if ((nod = (struct cron *)pool_alloc(&plcron, FALSE))) {
-       nod->expires = t + secs;
-       va_start(arg_ptr, fmt);
-       vsnprintf(nod->data, 1023, fmt, arg_ptr);
-       va_end(arg_ptr);
-       DLIST_APPEND(&lcron, (node_t *)nod);
-    }
-}
-
-
-
-static void zen_init(void)
-{
-    int num;
-
-    for (num = 0; zen_strings[num]; num++);
-    zen_num = num;
-}
-
-static char *zen(void)
-{
-    /*return( zen_strings[rand() % zen_num] ); */
-    if (zen_offset > zen_num)
-       zen_offset = 0;
-    return (zen_strings[zen_offset++]);
-}
-
-
-static bool eintr(void)
-{
-    if (errno == EINTR)
-       return TRUE;
-
-    return FALSE;
-}
diff --git a/mmsoftware/bot/zenbot.c b/mmsoftware/bot/zenbot.c
deleted file mode 100644 (file)
index a71ecd2..0000000
+++ /dev/null
@@ -1,1106 +0,0 @@
-/* $Id: zenbot.c,v 1.12 2004/10/22 14:28:26 mmondor Exp $ */
-
-/*
- * Copyright (C) 2002-2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-
-/* HEADERS */
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include <poll.h>
-#include <errno.h>
-
-#include <syslog.h>
-#include <time.h>
-#include <ctype.h>
-
-#include <mmreadcfg.h>
-#include <mmfd.h>
-#include <mmlist.h>
-#include <mmpool.h>
-#include <mmhash.h>
-#include <mmlog.h>
-#include <mmstring.h>
-
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: zenbot.c,v 1.12 2004/10/22 14:28:26 mmondor Exp $");
-
-
-
-
-/* DEFINITIONS */
-
-/* Defines a flood protection entry in a hash table */
-struct freq {
-    pnode_t node;
-    time_t expires;
-    bool ignore;
-    u_int64_t hash;
-    unsigned long freq;
-};
-
-/* An entry in the delayed output queue */
-struct cron {
-    pnode_t node;
-    time_t expires;
-    char data[512];
-};
-
-/* A channel we joined */
-struct channel {
-    pnode_t node;
-    u_int64_t channel_hash;
-    pool_t pchannel_users;
-    list_t channel_users;
-    int channel_limit, channel_mode;
-    char channel_name[64], channel_key[16];
-};
-
-/* A user on a channel */
-struct user {
-    pnode_t node;
-    u_int64_t user_hash;
-    int user_mode;
-    char user_nick[64];
-};
-
-/* This structure is used so that an irc line can be parsed once, for
- * various conditionals that may later on take place on the elements.
- * This structure is shared among all states and functions.
- */
-struct info {
-    fdbuf *fdb;                        /* Socket */
-    struct state *state;       /* Current state */
-    int code;                  /* Command code or -1 for text command */
-    int params;                        /* Number of extra parameters or 0 */
-    char line[512];            /* Actual IRC line we received */
-    char work[512];            /* Copy of line, split with \0s */
-    /* When appropriate, these will be set */
-    char *server;
-    char *nick, *ident, *host, *command;
-    char *param[10];
-    char *text;
-    /* Add other global data here if required */
-    char nickname[64];         /* Our own nick */
-    time_t zen_last;
-    time_t ping_last, ver_last;
-};
-
-/* Defines a state handler */
-struct handler_func {
-    int handler_code;          /* Mutually exclusive with command */
-    char *handler_command;
-    void (*handler_func)(struct info *);
-};
-
-/* Defines a state */
-struct state {
-    void (*state_init)(struct info *);
-    void (*state_exit)(struct info *);
-    struct handler_func *state_handlers;
-};
-
-/* Defined states */
-#define STATE_IDENT    0
-#define STATE_MAIN     1
-
-/* Configurable options */
-#define INPUT_TIMEOUT          300
-#define FLOOD_HOST_MAX         20
-#define FLOOD_HOST_TIME                60
-#define FLOOD_HOST_IGNORE      300
-#define FLOOD_USER_MAX         10
-#define FLOOD_USER_TIME                60
-#define FLOOD_USER_IGNORE      120
-#define IGN_NOTIFY             1
-#define REJOIN_DELAY           30
-#define ALLOW_PING             1
-#define PING_RATE              10
-#define ALLOW_VER              1
-#define VER_RATE               10
-#define VER_STRING "$Id: zenbot.c,v 1.12 2004/10/22 14:28:26 mmondor Exp $"
-#define ANSWER_RATE            120     /* For zenbot replies frequency */
-#define INITIAL_UMODE          "+iw"
-
-/*#define DEBUG                        1*/
-
-
-
-
-/* PROTOTYPES */
-
-int main(int, char **);
-static void main_loop(struct info *);
-static int allow_entry(pool_t *, list_t *, char *, unsigned long, int, long);
-static bool irc_match(char *, char *);
-static void irc_parse(struct info *);
-static void user_add(char *, char *);
-static struct channel *user_del(char *, char *);
-static void cron_add(int, char *, ...);
-
-static void ignore_user(struct info *);
-static void ignore_host(struct info *);
-static void ident_init(struct info *);
-static void ident_main(struct info *);
-static void main_init(struct info *);
-static void main_messaged(struct info *);
-static void main_noticed(struct info *);
-static void main_joined(struct info *);
-static void main_kicked(struct info *);
-static void main_parted(struct info *);
-static void main_quitted(struct info *);
-static void main_nick(struct info *);
-static void main_mode(struct info *);
-static void main_invited(struct info *);
-static void main_names(struct info *);
-
-static void zen_init(void);
-static char *zen(void);
-
-static bool eintr(void);
-
-
-
-/* GLOBALS */
-
-/* Various slab-buffered linked lists */
-static pool_t plusers, plhosts, plcron, plchans;
-static list_t lusers, lhosts, lcron, lchans;
-
-/* To map umode to bit number in umode bitfield */
-/* Modes which can be applied to ourself globally */
-static char *umodes = "agiknosw";
-/* Modes which can be applied to users (and ourself) on a channel */
-static char *cumodes = "ov";
-/* Modes which can be applied on a channel */
-static char *cmodes = "cikmnprstOR";   /* k and l require param */
-
-/* Here consists of the states definition table. Each state has a series
- * of handler functions, which will be called when a particular pattern
- * matches (with * and ? wildcards). These functions can optionally request
- * to change state by returning another state * than the one it was provided.
- */
-static struct handler_func state_ident_handlers[] = {
-    {376, NULL, ident_main},   /* End of MOTD */
-    {422, NULL, ident_main},   /* No MOTD */
-    {0, NULL, NULL}
-};
-static struct handler_func state_main_handlers[] = {
-    {0, "PRIVMSG", main_messaged},
-    {0, "NOTICE", main_noticed},
-    {0, "KICK", main_kicked},
-    {0, "PART", main_parted},
-    {0, "JOIN", main_joined},
-    {0, "QUIT", main_quitted},
-    {0, "NICK", main_nick},
-    {0, "MODE", main_mode},
-    {0, "INVITE", main_invited},
-    {353, NULL, main_names},
-    {0, NULL, NULL}
-};
-/* The definitions of the states, their optional init and exit code, and
- * a pointer to their various function handlers.
- */
-static struct state states[] = {
-    {ident_init, NULL, state_ident_handlers},
-    {main_init, NULL, state_main_handlers},
-    {NULL, NULL, NULL}
-};
-
-/* Channels we should join and make sure to remain in */
-static char *channels[] = {
-    "#c",
-    NULL
-};
-
-/* Zen koans */
-static int zen_num;            /* set by zen_init() */
-static int zen_offset = 0;     /* Current quote offset */
-static char *zen_strings[] = {
-    "The cypress tree in the yard.",
-    "Many moons ago.",
-    "Eat your bowl.",
-    "A bum on the hand, is better than two in the bush.",
-    "The definition of the states.",
-    "It is.",
-    "Yes.",
-    "No.",
-    "Long sessions.",
-    "The butterfly is silent when the eagle walks upon the sand.",
-    "Tantamount to painting your leg red and walking the dog.",
-    "Carrots.",
-    "A guiding light at the bottom of the firepit.",
-    "A sinking boat picking up people in the middle of the sea.",
-    "You have a wooden leg, does that make you a table?",
-    "It puts the lotion on its skin or else it gets the hose again.",
-    "Watch what cooks in the oven.",
-    "When he breathes short, he knows that he is breathing short, when he breathes deeply he also knows that he does.",
-    "What is the sound of one hand clapping?",
-    "What is your original face before your parents were born?",
-    "When the many are reduced to one, what is the one reduced to?",
-    "What is mu?",
-    "Bring out your mind here before me, and I will pacify it.",
-    "There! I have pacified your mind.",
-    "Here is a tall bamboo; there is a short one.",
-    "Three pound of flax!",
-    "Matchbox is a noise. Is this a noise?",
-    "Every natural fact is a symbol of some spiritual fact.",
-    "The highest human purpose is always to reinvent and celebrate the sacred.",
-    "People who take the time to be alone usually have depth, and quiet reserve.",
-    "Check out http://google.com, it is a very good site.",
-    "We think in generalities, but we live in details.",
-    "The oak tree in the garden.",
-    "Insects, grass and trees you must not hurt.",
-    "Cultivate the garden within.",
-    "This cabbage, these carrots, these potatoes, these onions ... will soon become me.  Such a tasty fact!",
-    "Learning how to operate a soul figures to take time.",
-    "There's nothing much, really, to say.",
-    "The Tao exists in the crickets... in the grasses... in tiles and bricks... and in shit and piss.",
-    "A garden is a private world or it is nothing.",
-    "One real world is enough.",
-    "Right here, right now.",
-    "Mu!",
-    "Before your parents gave birth to you.",
-    "Neither standing nor sitting will do, now what will you do?",
-    "What do you do?",
-    "Not relying on words or letters.",
-    "The dinner is never complete without some meat in your seat.",
-    "A clique that seeks power usually through intrigue.",
-    "NULL.",
-    "void *(void *)(void *).",
-    NULL
-};
-
-
-
-/* FUNCTIONS */
-
-static void ignore_user(struct info *data)
-{
-    if (IGN_NOTIFY) {
-       fdbprintf(data->fdb,
-                 "PRIVMSG %s :Ignoring your ident for %d seconds.\r\n",
-                 data->nick, FLOOD_USER_IGNORE);
-       /* fdbprintf(data->fdb, "WHOIS :%s\r\n", data->nick); */
-    }
-}
-
-static void ignore_host(struct info *data)
-{
-    if (IGN_NOTIFY) {
-       fdbprintf(data->fdb,
-                 "PRIVMSG %s :Ignoring your hostname for %d seconds.\r\n",
-                 data->nick, FLOOD_HOST_IGNORE);
-       /* fdbprintf(data->fdb, "WHOIS :%s\r\n", data->nick); */
-    }
-}
-
-
-static void ident_init(struct info *data)
-{
-    data->zen_last = time(NULL);
-    fdbprintf(data->fdb, "USER %s %s %s %s\r\n", data->nickname,
-             data->nickname, data->nickname, data->nickname);
-    fdbprintf(data->fdb, "NICK %s\r\n", data->nickname);
-}
-
-static void ident_main(struct info *data)
-{
-    /* Simply switch to the main state */
-    data->state = &states[STATE_MAIN];
-}
-
-
-static void main_init(struct info *data)
-{
-    int i;
-
-    /* Set our initial umode */
-    fdbprintf(data->fdb, "MODE %s :%s\r\n", data->nickname, INITIAL_UMODE);
-
-    /* Join channels */
-    for (i = 0; channels[i]; i++)
-       fdbprintf(data->fdb, "JOIN :%s\r\n", channels[i]);
-}
-
-static void main_messaged(struct info *data)
-{
-    char *str;
-    time_t t = time(NULL);
-    int r;
-
-    /* Handle PING and VERSION CTCP requests */
-    if (ALLOW_PING && !mm_strncmp(data->text, "\001PING ", 6)) {
-       long tim;
-       if (t - data->ping_last > PING_RATE) {
-           tim = atol(&data->text[6]);
-           fdbprintf(data->fdb, "NOTICE %s :\001PING %ld\001\r\n",
-                     data->nick, tim);
-           data->ping_last = t;
-       }
-       return;
-    }
-    if (ALLOW_VER && !mm_strcmp(data->text, "\001VERSION\001")) {
-       if (t - data->ver_last > VER_RATE) {
-           fdbprintf(data->fdb, "NOTICE %s :\001VERSION %s\001\r\n",
-                     data->nick, VER_STRING);
-           data->ver_last = t;
-       }
-       return;
-    }
-
-    /* Reply to user via /msg or on channel depending on origin.
-     * Also make sure to not answer too frequently.
-     */
-    if (t - data->zen_last > ANSWER_RATE) {
-       if (irc_match(data->text, "*why *") ||
-           irc_match(data->text, "*how *") ||
-           irc_match(data->text, "*who *") ||
-           irc_match(data->text, "*what *") ||
-           irc_match(data->text, "*where *") ||
-           irc_match(data->text, "*when *")) {
-           data->zen_last = t;
-           str = zen();
-           /* Let's simulate a human delay (2 - 10 secs) */
-           r = 2 + (rand() % 8);
-           if (!mm_strcmp(data->param[0], data->nickname))
-               cron_add(r, "PRIVMSG %s :%s\r\n", data->nick, str);
-           else
-               cron_add(r, "PRIVMSG %s :%s: %s\r\n", data->param[0],
-                        data->nick, str);
-       }
-    }
-}
-
-static void main_noticed(struct info *data)
-{
-    /* XXX */
-}
-
-static void main_joined(struct info *data)
-{
-    struct channel *ch;
-
-    /* data->text consists of channel name, data->nick of nickname */
-    if (!mm_strcmp(data->nick, data->nickname)) {
-       /* We have joined a new channel, create new channel node with it's
-        * users list
-        */
-       if ((ch = (struct channel *)pool_alloc(&plchans, TRUE))) {
-           if (pool_init(&ch->pchannel_users, "pchannel_users",
-                       malloc, free, NULL, NULL, sizeof(struct user),
-                       4096 / sizeof(struct user), 0, 0)) {
-               DLIST_INIT(&ch->channel_users);
-               ch->channel_hash = mm_strhash64(data->text);
-               mm_strcpy(ch->channel_name, data->text);
-               DLIST_APPEND(&lchans, (node_t *)ch);
-           }
-       }
-    } else {
-       /* Another user joined one of the channels we are in, update
-        * corresponding channel's userlist
-        */
-       user_add(data->text, data->nick);
-    }
-}
-
-static void main_kicked(struct info *data)
-{
-    struct channel *ch;
-
-    /* data->param[0] consists of channel name, data->param[1] of nick */
-    ch = user_del(data->param[0], data->param[1]);
-    if (!mm_strcmp(data->param[1], data->nickname)) {
-       /* We have been kicked out of the channel, free all channel
-        * info and send a delayed join request
-        */
-       DLIST_UNLINK(&lchans, (node_t *)ch);
-       pool_destroy(&ch->pchannel_users);
-       pool_free((pnode_t *)ch);
-       cron_add(REJOIN_DELAY, "JOIN :%s\r\n", data->param[0]);
-    }
-}
-
-static void main_parted(struct info *data)
-{
-    struct channel *ch;
-
-    /* data->nick consists of nickname, data->param[0] of channel name */
-    ch = user_del(data->param[0], data->nick);
-    if (!mm_strcmp(data->nick, data->nickname)) {
-       /* We have left a channel, free all channel info */
-       DLIST_UNLINK(&lchans, (node_t *)ch);
-       pool_destroy(&ch->pchannel_users);
-       pool_free((pnode_t *)ch);
-    }
-}
-
-static void main_quitted(struct info *data)
-{
-    struct channel *ch, *tmp;
-
-    user_del(NULL, data->nick);
-    if (!mm_strcmp(data->nick, data->nickname)) {
-       /* We have quitted, free all channel info */
-       ch = (struct channel *)lchans.top;
-       while (ch) {
-           tmp = (struct channel *)ch->node.node.next;
-           DLIST_UNLINK(&lchans, (node_t *)ch);
-           pool_free((pnode_t *)ch);
-           ch = tmp;
-       }
-    }
-}
-
-static void main_nick(struct info *data)
-{
-    u_int64_t hash, nhash;
-    struct channel *ch;
-    struct user *us;
-
-    /* A user changed nickname, make sure to update it in all our channels
-     * the user is in. If we are the one who changed nick, also update our
-     * internal own nickname record.
-     */
-    hash = mm_strhash64(data->nick);
-    nhash = mm_strhash64(data->text);
-
-    ch = (struct channel *)lchans.top;
-    while (ch) {
-       us = (struct user *)ch->channel_users.top;
-       while (us) {
-           if (us->user_hash == hash)
-               break;
-           us = (struct user *)us->node.node.next;
-       }
-       if (us) {
-           us->user_hash = nhash;
-           mm_strcpy(us->user_nick, data->text);
-       }
-       ch = (struct channel *)ch->node.node.next;
-    }
-    /*
-    if (!mm_strcmp(data->nick, data->nickname)) {
-       mm_strncpy(data->nickname, data->text, 63);
-       XXX Update hash also?
-    }
-    */
-}
-
-static void main_mode(struct info *data)
-{
-    /* A mode change occured for either ourself, a channel or another user.
-     * we only record those for now, but action could be taken also on certain
-     * mode change events. XXX
-     */
-    /* :PhadThai!mmondor@gobot.xisop MODE #netbsd-devel +o nanobit
-     * :nanobit MODE nanobit :+iw
-     */
-    if (data->ident && data->param[0] && *data->param[0] == '#') {
-       /* cmode or cumode change */
-    } else {
-       /* umode change */
-#ifdef DEBUG
-       printf("UMODE\n");
-#endif
-    }
-}
-
-static void main_invited(struct info *data)
-{
-    /* XXX */
-}
-
-static void main_names(struct info *data)
-{
-    char *words[64];           /* XXX check how many max */
-    int cols, i;
-
-    /* data->param[2] consists of channel name, and data->text of nicks */
-    if ((cols = mm_straspl(words, data->text, 63)) > 0) {
-       for (i = 0; i < cols; i++)
-           user_add(data->param[2], words[i]);
-    }
-}
-
-
-/* The main startup function */
-int main(int argc, char **argv)
-{
-    int port, fd;
-    char *server;
-    struct sockaddr_in client;
-    struct in_addr iaddr;
-    struct info data;
-
-    fdfuncs fdf = {
-       malloc,
-       free,
-       poll,
-       read,
-       write,
-       sleep,
-       usleep,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       eintr
-    };
-
-    if (argc != 3) {
-       printf("Usage: zenbot <nick> <ipaddress>\n");
-       exit (-1);
-    }
-
-    mm_memclr(&data, sizeof(data));
-
-    /* Parse arguments */
-    server = argv[2];
-    mm_strncpy(data.nickname, argv[1], 63);
-    port = 6667;
-
-    /* Zen setup */
-    zen_init();
-
-    if (pool_init(&plusers, "plusers", malloc, free, NULL, NULL,
-               sizeof(struct freq), 8192 / sizeof(struct freq), 0, 0)) {
-       DLIST_INIT(&lusers);
-       if (pool_init(&plhosts, "plhosts", malloc, free, NULL, NULL,
-                   sizeof(struct freq), 8192 / sizeof(struct freq), 0, 0)) {
-           DLIST_INIT(&lhosts);
-           if (pool_init(&plcron, "plcron", malloc, free, NULL, NULL,
-                       sizeof(struct cron), 8192 / sizeof(struct cron),
-                       0, 0)) {
-               DLIST_INIT(&lcron);
-               if (pool_init(&plchans, "plchans", malloc, free, NULL, NULL,
-                           sizeof(struct channel),
-                           8192 / sizeof(struct channel), 0, 0)) {
-                   DLIST_INIT(&lchans);
-                   /* Prepare our fd buffering wrapper */
-                   if ((data.fdb = fdbopen(&fdf, NULL, -1, 4096, 4096, 1024,
-                                   1024, INPUT_TIMEOUT * 1000,
-                                   INPUT_TIMEOUT * 1000, FALSE))) {
-                       /* Loop indefinitely */
-                       for (;;) {
-                           /* Connect to server */
-                           if ((fd = socket(AF_INET, SOCK_STREAM, 0)) != -1) {
-                               mm_memclr(&client, sizeof(struct sockaddr_in));
-                               if ((inet_aton(server, &iaddr))) {
-                                   client.sin_family = AF_INET;
-                                   client.sin_addr.s_addr = iaddr.s_addr;
-                                   client.sin_port = htons(port);
-                                   if ((connect(fd,
-                                           (struct sockaddr *)&client,
-                                           sizeof(struct sockaddr_in)))
-                                           != -1) {
-                                       fcntl(fd, F_SETFL, O_NONBLOCK);
-                                       fdbparam_set(data.fdb, fd, FDBP_FD);
-                                       /* Serve our purpose */
-                                       data.state = &states[STATE_IDENT];
-                                       main_loop(&data);
-                                       fdbflushr(data.fdb);
-                                       fdbflushw(data.fdb);
-                                       fdbparam_set(data.fdb, -1, FDBP_FD);
-                                   } else
-                                       sleep(30);
-                               }
-                               close(fd);
-                           }
-                       }
-                       fdbclose(data.fdb);
-                   }
-                   pool_destroy(&plchans);
-               }
-               pool_destroy(&plcron);
-           }
-           pool_destroy(&plhosts);
-       }
-       pool_destroy(&plusers);
-    }
-
-    exit(0);
-}
-
-
-/* This function consists of the main state switcher loop, and basically
- * reads lines, calling the matching function handlers for the current
- * state. When a state switch occurs, exit code of the current state is
- * executed, and init code of the new state, if any.
- * We only return if a handler function returns a NULL pointer, or if
- * we loose connection with the server.
- * We internally take care of PING replies.
- */
-static void main_loop(struct info *data)
-{
-    struct state *curstate;
-    struct handler_func *fn;
-    int i;
-
-    if (data->state->state_init)
-       data->state->state_init(data);
-
-    while (TRUE) {
-       struct cron *nod, *tmp;
-       time_t t;
-
-       /* Verify if any queued data has expired and should be released out.
-        * unfortunately because of the way we currently work, some IRC
-        * activity is required to trigger this. XXX Ideally the fdbgets()
-        * timeout should be set to 1 when there is queued data, and timeout
-        * should not be assumed to be a server/connection failiure. For now,
-        * this should work fine on a channel with activity, or if we are
-        * on multiple channels.
-        */
-       t = time(NULL);
-       nod = (struct cron *)lcron.top;
-       while (nod) {
-           tmp = (struct cron *)nod->node.node.next;
-           if (nod->expires < t) {
-               DLIST_UNLINK(&lcron, (node_t *)nod);
-               fdbputs(data->fdb, nod->data);
-               pool_free((pnode_t *)nod);
-           }
-           nod = tmp;
-       }
-
-       fdbflushw(data->fdb);
-
-       if ((i = fdbgets(data->fdb, data->line, 511, FALSE)) > -1) {
-
-           /* We got a line, check if there exists any handler to serve
-            * it within current state. Execute the handler if required,
-            * and perform sane state switching if requested by a handler.
-            */
-
-           if (!mm_strncmp(data->line, "PING :", 6)) {
-               /* Transform PING to PONG and reply to server */
-               data->line[1] = 'O';
-               fdbprintf(data->fdb, "%s\r\n", data->line);
-               continue;
-           }
-
-           irc_parse(data);
-
-           /* Useful for debugging */
-#ifdef DEBUG
-           fwrite("\033[1m", 4, 1, stdout);
-           fwrite(data->line, i, 1, stdout);
-           fwrite("\r\n", 2, 1, stdout);
-           fwrite("\033[0m", 4, 1, stdout);
-           fflush(stdout);
-           printf("code: %d server: '%s' nick: '%s' ident: '%s' host: '%s' command: '%s' text: '%s' params: %d ",
-                data->code, data->server, data->nick, data->ident,
-                data->host, data->command, data->text, data->params);
-           for (i = 0; i < data->params; i++)
-               printf("param[%d]: '%s' ", i, data->param[i]);
-           printf("\r\n\r\n");
-           fflush(stdout);
-#endif
-
-           if (data->code == -1 && data->ident) {
-               int res;
-               bool allow = FALSE;
-
-               /* Check against flood by ident and hostname */
-               if (!(res = allow_entry(&plhosts, &lhosts, data->host,
-                               FLOOD_HOST_MAX, FLOOD_HOST_TIME,
-                                       FLOOD_HOST_IGNORE))) {
-                   if (!(res = allow_entry(&plusers, &lusers, data->ident,
-                                   FLOOD_USER_MAX, FLOOD_USER_TIME,
-                                   FLOOD_USER_IGNORE)))
-                       allow = TRUE;
-                   else if (res == 2)
-                       ignore_user(data);
-               } else if (res == 2)
-                   ignore_host(data);
-               if (!allow)
-                   continue;
-           }
-
-           curstate = data->state;
-           fn = curstate->state_handlers;
-           while (fn->handler_func) {
-               bool allow;
-
-               allow = FALSE;
-               if (fn->handler_code && data->code != -1) {
-                   if (fn->handler_code == data->code)
-                       allow = TRUE;
-               } else if (fn->handler_command && data->command) {
-                   if (!mm_strcmp(fn->handler_command, data->command))
-                       allow = TRUE;
-               }
-               if (allow) {
-                   /* Execute handler for matching pattern */
-                   fn->handler_func(data);
-                   if (data->state != curstate) {
-                       /* Perform state switching */
-                       if (curstate->state_exit)
-                           curstate->state_exit(data);
-                       if (data->state->state_init)
-                           data->state->state_init(data);
-                   }
-                   break;
-               }
-               fn++;
-           }
-
-       } else
-           break;
-    }
-}
-
-
-/* This function is useful to easily perform flood quota checking on nicks
- * and/or hosts. Returns 0 if the entry is allowed, 1 if it is not, 2 if
- * it just started to be ignored.
- */
-static int
-allow_entry(pool_t *pool, list_t *lst, char *entry, unsigned long max,
-       int secs, long igndelay)
-{
-    u_int64_t hash = mm_strhash64(entry);
-    int ret = 0;
-    struct freq *node, *tmp;
-    time_t t = time(NULL);
-
-    /* Locate if entry exists */
-    node = (struct freq *)lst->top;
-    while (node) {
-       tmp = (struct freq *)node->node.node.next;
-       if (node->expires < t) {
-           /* Expired, drop this entry */
-           DLIST_UNLINK(lst, (node_t *)node);
-           pool_free((pnode_t *)node);
-       } else if (node->hash == hash)
-           break;
-       node = tmp;
-    }
-    if (node) {
-       /* Entry existed, increase frequency and optionally toggle ignore */
-       node->freq++;
-       if (!node->ignore) {
-           if (node->freq > max) {
-               node->ignore = TRUE;
-               node->expires += igndelay;
-               ret = 2;
-           }
-       } else
-           ret = 1;
-    } else {
-       /* Add new entry */
-       if ((node = (struct freq *)pool_alloc(pool, FALSE))) {
-           node->expires = t + secs;
-           node->ignore = FALSE;
-           node->hash = hash;
-           node->freq = 1;
-           DLIST_APPEND(lst, (node_t *)node);
-       }
-    }
-
-    return (ret);
-}
-
-
-/* This function returns weither or not pat matches string.
- * We only perform simple * and ? pattern matching, case-sensitive.
- */
-static bool irc_match(char *str, char *pat)
-{
-    while (*pat ^ '*') {
-       if (!*str) {
-           if (*pat)
-               return (FALSE);
-           else
-               return (TRUE);
-       }
-       if (*str ^ *pat && *pat ^ '?')
-           return (FALSE);
-       pat++;
-       str++;
-    }
-
-    while (pat[1] == '*')
-       pat++;
-
-    do {
-       if (irc_match(str, pat + 1))
-           return (TRUE);
-    } while (*str++);
-
-    return (FALSE);
-}
-
-
-/* Some mmondor-style string parsing magic, fill data fields according to
- * IRC protocol line
- */
-static void irc_parse(struct info *data)
-{
-    char *ptr, *optr, *words[16];
-    size_t cols;
-    int i, i2;
-
-    /* Init, everything set to NULL, and code to -1 by default */
-    mm_strcpy(data->work, data->line);
-    ptr = data->work;
-    data->code = -1;
-    data->params = 0;
-    data->server = data->nick = data->ident = data->host = data->command =
-       data->text = NULL;
-
-    if (*ptr == ':') {
-       /* IRC lines start with ':' */
-       ptr++;
-       optr = ptr;
-       while (*ptr && *ptr != ':')
-           ptr++;
-       if (*ptr == ':') {
-           /* Multiword text field */
-           *ptr++ = 0;
-           data->text = ptr;
-       }
-       if ((cols = mm_straspl(words, optr, 16)) > 1) {
-           /* Determine the type of IRC protocol line and fill corresponding
-            * pointers.
-            */
-           if ((i = atoi(words[1]))) {
-               /* Code based line */
-               data->server = *words;
-               data->code = i;
-           } else {
-               /* Text command based line */
-               ptr = *words;
-               while (*ptr && *ptr != '.' && *ptr != '!')
-                   ptr++;
-               if (*ptr == '.')
-                   /* Server name in first column */
-                   data->server = *words;
-               else {
-                   /* Nickname in first column, optional ident and host */
-                   ptr = data->nick = *words;
-                   while (*ptr && *ptr != '!')
-                       ptr++;
-                   if (*ptr == '!') {
-                       *ptr++ = 0;
-                       data->ident = ptr;
-                       while (*ptr && *ptr != '@')
-                           ptr++;
-                       if (*ptr == '@') {
-                           *ptr++ = 0;
-                           data->host = ptr;
-                       }
-                   }
-               }
-               data->command = words[1];
-           }
-           if (cols > 2) {
-               /* Additional parameters before text */
-               i = 0;
-               for (i2 = 2; i2 < cols; i2++)
-                   data->param[i++] = words[i2];
-               data->params = i;
-           }
-       }
-    }
-}
-
-
-/* Adds a user to a channel, also checks for @ and + in start of nick to
- * set according mode.
- */
-static void user_add(char *chan, char *nick)
-{
-    u_int64_t chanhash, nickhash;
-    struct channel *ch;
-    struct user *us;
-    int mode;
-
-    mm_strlower(chan);
-    chanhash = mm_strhash64(chan);
-
-    mode = 0;
-    if (*nick) {
-       if (*nick == '@') {
-           mode |= (1L << 0);
-           nick++;
-       } else if (*nick == '+') {
-           mode |= (1L << 1);
-           nick++;
-       }
-    }
-    nickhash = mm_strhash64(nick);
-
-    /* Find channel user should be added to */
-    ch = (struct channel *)lchans.top;
-    while (ch) {
-       if (ch->channel_hash == chanhash)
-           break;
-       ch = (struct channel *)ch->node.node.next;
-    }
-    if (ch) {
-       /* We found channel */
-       if ((us = (struct user *)pool_alloc(&ch->pchannel_users, FALSE))) {
-           mm_strcpy(us->user_nick, nick);
-           us->user_hash = nickhash;
-           us->user_mode = mode;
-#ifdef DEBUG
-           printf("ADDED USER '%s' TO CHANNEL '%s'\n", nick, chan);
-#endif
-           DLIST_APPEND(&ch->channel_users, (node_t *)us);
-       }
-    }
-}
-
-
-/* Deletes a nick from specified channel, or from all channels if chan is NULL
- */
-static struct channel *user_del(char *chan, char *nick)
-{
-    u_int64_t chanhash, nickhash;
-    struct channel *ch;
-    struct user *us;
-
-    nickhash = mm_strhash64(nick);
-    ch = NULL;
-
-    if (chan) {
-       /* Delete user on specified channel */
-       mm_strlower(chan);
-       chanhash = mm_strhash64(chan);
-       ch = (struct channel *)lchans.top;
-       while (ch) {
-           if (ch->channel_hash == chanhash)
-               break;
-           ch = (struct channel *)ch->node.node.next;
-       }
-       if (ch) {
-           /* We found channel */
-           us = (struct user *)ch->channel_users.top;
-           while (us) {
-               if (us->user_hash == nickhash)
-                   break;
-               us = (struct user *)us->node.node.next;
-           }
-           if (us) {
-               /* We found nick */
-               DLIST_UNLINK(&ch->channel_users, (node_t *)us);
-               pool_free((pnode_t *)us);
-#ifdef DEBUG
-               printf("DELETED USER '%s' FROM CHANNEL '%s'\n", nick,
-                      chan);
-#endif
-           }
-       }
-    } else {
-       /* Delete user on all channels */
-       ch = (struct channel *)lchans.top;
-       while (ch) {
-           us = (struct user *)ch->channel_users.top;
-           while (us) {
-               if (us->user_hash == nickhash) {
-                   DLIST_UNLINK(&ch->channel_users, (node_t *)us);
-                   pool_free((pnode_t *)us);
-                   break;
-               }
-               us = (struct user *)us->node.node.next;
-           }
-           ch = (struct channel *)ch->node.node.next;
-       }
-#ifdef DEBUG
-       printf("DELETED USER '%s' FROM ALL CHANNELS\n", nick);
-#endif
-    }
-
-    return (ch);
-}
-
-
-/* Allows to queue data to be sent after a certain delay has been observed. */
-static void cron_add(int secs, char *fmt, ...)
-{
-    struct cron *nod;
-    time_t t = time(NULL);
-    va_list arg_ptr;
-
-    if ((nod = (struct cron *)pool_alloc(&plcron, FALSE))) {
-       nod->expires = t + secs;
-       va_start(arg_ptr, fmt);
-       vsnprintf(nod->data, 1023, fmt, arg_ptr);
-       va_end(arg_ptr);
-       DLIST_APPEND(&lcron, (node_t *)nod);
-    }
-}
-
-
-
-static void zen_init(void)
-{
-    int num;
-
-    for (num = 0; zen_strings[num]; num++);
-    zen_num = num;
-}
-
-static char *zen(void)
-{
-    /*return( zen_strings[rand() % zen_num] ); */
-    if (zen_offset > zen_num)
-       zen_offset = 0;
-    return (zen_strings[zen_offset++]);
-}
-
-
-static bool eintr(void)
-{
-    if (errno == EINTR)
-       return TRUE;
-
-    return FALSE;
-}
-
diff --git a/mmsoftware/clean.sh b/mmsoftware/clean.sh
deleted file mode 100755 (executable)
index a5af627..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-# $Id: clean.sh,v 1.2 2003/07/02 17:20:52 mmondor Exp $
-
-. mmlib/makefuncs.sh
-
-cd mmlib/
-clean mmlib
-cd ../
-
-cd mmpasswd/
-clean mmpasswd
-cd ../
-
-cd mmstatd/src/
-clean mmstatd
-cd ../../
-cd apache-mmstat/
-clean apache-mmstat
-cd ../
-
-#cd mmsucom/
-#clean mmsucom
-#cd ../
-
-cd mmftpd/src/
-clean mmftpd
-cd ../../
-
-cd mmmail/src/mmsmtpd/
-clean mmsmtpd
-cd ../mmpop3d
-clean mmpop3d
-cd ../../../
diff --git a/mmsoftware/install.sh b/mmsoftware/install.sh
deleted file mode 100755 (executable)
index 410a986..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-#!/bin/sh
-# $Id: install.sh,v 1.9 2003/10/23 01:01:15 mmondor Exp $
-
-if [ "$1" = "help" ]; then
-       echo
-       echo 'You can optionally set the following environment variables'
-       echo 'to customize the installation process. For each is shown an'
-       echo 'example using the default value followed by a breif description.'
-       echo
-       echo 'export MMLAUNCH="TRUE"'
-       echo '   Tells the install process to immediately launch the daemon(s)'
-       echo '   They are automatically killed before the binaries are copied'
-       echo '   over the old ones as is necessary with some systems. The'
-       echo '   default is to not start them back automatically.'
-       echo
-       echo 'export MMPREFIX="/usr/local"'
-       echo '   Allows to set the installation base directory. All files but'
-       echo '   configuration ones will be installed in directories relative'
-       echo '   to this one.'
-       echo
-       echo 'export MMCONFDIR="/etc"'
-       echo '   Directory in which configuration files should be stored.'
-       echo
-       echo 'export MMDEFAULTUSER="0"'
-       echo '   User new files and directories should be owned by, using'
-       echo '   user id or name.'
-       echo
-       echo 'export MMDEFAULTGROUP="0"'
-       echo '   Group new files and directories should be under, using id'
-       echo '   or name.'
-       echo
-       echo 'export MMADMINGROUP="staff"'
-       echo '   The administrators group, these can for instance view and the'
-       echo '   rotate mmstat statistics and execute mmpasswd. Will be'
-       echo '   created automatically if necessary.'
-       echo
-       echo 'export MMSTATDIR="/var/mmstatd"'
-       echo '   The directory in which mmstatd will store the stats database'
-       echo '   and log files.'
-       echo
-       echo 'export MMSTATDUSER="mmstatd"'
-       echo '   The user mmstatd will run under, to be automatically created.'
-       echo
-       echo 'export MMSTATDGROUP="mmstat"'
-       echo '   Group the mmstatd user should be part of, automatically'
-       echo '   created.'
-       echo
-       echo 'export MMFTPDUSER="mmftpd"'
-       echo '   The user mmftpd will run under, to be automatically created.'
-       echo
-       echo 'export MMFTPDGROUP="mmftpd"'
-       echo '   Group the mmftpd user should be part of, automatically'
-       echo '   created. The mmftpdpasswd configuration file will be readable'
-       echo '   by this group.'
-       echo
-       echo 'export MMMAILUSER="mmmail"'
-       echo '   The user mmmail daemons should run under, will be created'
-       echo '   automatically if nonexisting.'
-       echo
-       echo 'export MMMAILGROUP="mmmail"'
-       echo '   Group the mmmail user should be part of. Created if needed.'
-       echo
-       exit
-fi
-
-# Set defaults if not set
-if [ -z "$MMLAUNCH" ]; then
-       export MMLAUNCH='FALSE'
-fi
-if [ -z "$MMPREFIX" ]; then
-       export MMPREFIX='/usr/local'
-fi
-if [ -z "$MMCONFDIR" ]; then
-       export MMCONFDIR='/etc'
-fi
-if [ -z "$MMDEFAULTUSER" ]; then
-       export MMDEFAULTUSER='0'
-fi
-if [ -z "$MMDEFAULTGROUP" ]; then
-       export MMDEFAULTGROUP='0'
-fi
-if [ -z "$MMADMINGROUP" ]; then
-       export MMADMINGROUP='staff'
-fi
-if [ -z "$MMSTATDIR" ]; then
-       export MMSTATDIR='/var/mmstatd'
-fi
-if [ -z "$MMSTATDUSER" ]; then
-       export MMSTATDUSER='mmstatd'
-fi
-if [ -z "$MMSTATDGROUP" ]; then
-       export MMSTATDGROUP='mmstat'
-fi
-if [ -z "$MMFTPDUSER" ]; then
-       export MMFTPDUSER='mmftpd'
-fi
-if [ -z "$MMFTPDGROUP" ]; then
-       export MMFTPDGROUP='mmftpd'
-fi
-if [ -z "$MMMAILUSER" ]; then
-       export MMMAILUSER='mmmail'
-fi
-if [ -z "$MMMAILGROUP" ]; then
-       export MMMAILGROUP='mmmail'
-fi
-
-. mmlib/makefuncs.sh
-
-instgroup $MMADMINGROUP
-
-cd mmlib/
-instman mmfd.3 3
-instman mmfifo.3 3
-instman mmlifo.3 3
-instman mmlist.3 3
-instman mmpool.3 3
-instman mmpath.3 3
-instman mmstat.3 3
-instman mmhash.3 3
-instman mmlimitrate.3 3
-cd ../
-cd apache-mmstat/
-instman apache-mmstat.8 8
-cd ../
-
-cd mmpasswd/
-instbin mmpasswd 750 $MMADMINGROUP
-instman mmpasswd.8 8
-cd ../
-
-cd mmstatd/src/
-instuser $MMSTATDUSER $MMSTATDGROUP
-killbin mmstatd
-instbin mmstatd 700
-instbin mmstat 750 $MMADMINGROUP
-instman mmstat.8 8
-instman mmstatd.8 8
-instman mmstatd.conf.5 5
-cd ../etc/
-instconf mmstatd.conf 640 $MMSTATDGROUP
-instdir $MMSTATDIR 750 $MMSTATDUSER $MMSTATDGROUP
-if [ "$MMLAUNCH" = "TRUE" ]; then
-       startbin mmstatd $MMCONFDIR/mmstatd.conf
-fi
-cd ../../
-cd apache-mmstat/
-instbin apache-mmstat 700
-cd ../
-
-cd mmftpd/src/
-instuser $MMFTPDUSER $MMFTPDGROUP
-killbin mmftpd
-instbin mmftpd 700
-instman mmftpd.8 8
-instman mmftpd.conf.5 5
-instman mmftpdpasswd.5 5
-cd ../etc/
-instconf mmftpd.conf 600
-instconf mmftpdpasswd 640 $MMFTPDGROUP
-if [ "$MMLAUNCH" = "TRUE" ]; then
-       startbin mmftpd $MMCONFDIR/mmftpd.conf
-fi
-cd ../../
-
-cd mmmail/src/mmsmtpd/
-instuser $MMMAILUSER $MMMAILGROUP
-killbin mmsmtpd
-instbin mmsmtpd 700
-instman mmsmtpd.8 8
-instman mmsmtpd.conf.5 5
-cd ../mmpop3d
-killbin mmpop3d
-instbin mmpop3d 700
-instman mmpop3d.8 8
-instman mmpop3d.conf.5 5
-cd ../../etc
-instconf mmsmtpd.conf 600
-instconf mmpop3d.conf 600
-if [ "$MMLAUNCH" = "TRUE" ]; then
-       startbin mmsmtpd $MMCONFDIR/mmsmtpd.conf
-       startbin mmpop3d $MMCONFDIR/mmpop3d.conf
-fi
-cd ../src
-instman mmmail.8 8
-cd ../../
-
-echo
-echo "*** Please read the following man pages ***"
-echo
-echo "all users: mmstat(8), mmstatd(8), mmstatd.conf(5), mmpasswd(8),"
-echo "           apache-mmstat(8)"
-echo "mmftpd users: mmftpd(8), mmftpd.conf(5), mmftpdpasswd(5)"
-echo "mmmail users: mmmail(8), mmsmtpd(8), mmsmtpd.conf(5), mmpop3d(8),"
-echo "              mmpop3d.conf(5)"
-echo "source auditors: mmstat(3), mmfd(3), mmlist(3), mmpool(3), mmfifo(3),"
-echo "                 mmlifo(3), mmpath(3), mmhash(3), mmlimitrate(3)"
-echo
-echo "Thank you for using mmsoftware."
-echo
diff --git a/mmsoftware/js/classes/TODO.txt b/mmsoftware/js/classes/TODO.txt
deleted file mode 100644 (file)
index f323174..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-- Implement security policy module
-- Add berkeley db4 support
-- Add a Timer module
-  - Should have sleep, usleep, nanosleep etc, as well as setitimer support
-    and/or possibly support mmalarm(3)
-- Add a Signal module to install custom JS handlers.  Ideally, signal would
-  get queued then user handler called when exiting the signal handler...
-  With automatic signal blocking during processing.
diff --git a/mmsoftware/js/classes/js_cgi.c b/mmsoftware/js/classes/js_cgi.c
deleted file mode 100644 (file)
index abfd774..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/* $Id: js_cgi.c,v 1.1 2006/09/08 08:04:58 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <stdint.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-#include <js_cgi.h>
-
-
-
-
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-
-
-/*
- * Static prototypes
- */
-static JSBool  cgi_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSBool  cgi_sm_JSON(JSContext *, JSObject *, uintN, jsval *, jsval *);
-
-
-
-/*
- * Static globals
- */
-
-/*
- * General purpose string buffer (note that this is not thread-safe).
- * Allows to optimize functions such as PQescapeStringConn().
- */
-static char    *buffer = NULL;
-static size_t  buffer_size = 0;
-static Oid     *param_types = NULL;
-static char    **param_values = NULL;
-static int     *param_lengths = NULL;
-static int     *param_formats = NULL;
-static int     param_entries = 0;
-
-/* PG class */
-static JSClass cgi_class = {
-       "CGI", 0, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,
-       JS_ConvertStub, JS_FinalizeStub
-};
-
-/* Provided static methods */
-static JSFunctionSpec cgi_smethods[] = {
-       { "JSON", cgi_sm_json, 2, 0, 0 },       /* XXX Check naming */
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/* Provided static properties */
-
-#define SP(n) \
-    { #n, n }
-
-static struct property_spec    cgi_sprops[] = {
-       { NULL, 0 }
-};
-
-#undef SP
-
-
-/*
- * CGI object control
- */
-
-JSObject *
-js_InitCGIClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &cgi_class, cgi_constructor, 0,
-           NULL, NULL, NULL, cgi_smethods)) == NULL) {
-               (void) fprintf(stderr, "Error initializing CGI class\n");
-               goto err;
-       }
-
-       /* Create static properties */
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "CGI: JS_GetConstructor == NULL\n");
-               goto err;
-       }
-       for (sp = cgi_sprops; sp->name != NULL; sp++) {
-               if (!JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT)) {
-                       (void) fprintf(stderr,
-                           "CGI: Error defining property %s\n", sp->name);
-                       goto err;
-               }
-       }
-
-       return proto;
-
-err:
-       return NULL;
-}
-
-/* Non instanciable */
-static JSBool
-cgi_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("CGI class uninstanciable");
-
-       return JS_FALSE;
-}
-
-
-/*
- * CGI object static methods
- */
-
-/*
- * Secure replacement for eval('o = ' + user_defined_data); which is unsafe.
- * We only support Strings, (using ""), Arrays (using []) objects (using {})
- * and numbers (using no special marker).  This function allows recursiveness
- * up to a certain level allowed by the function.  We return an object with
- * the unserialized data, or null on error.  We don't allow functions.
- */
-static JSBool
-cgi_sm_json(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JS_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if (!JS_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-
-       /* XXX */
-       json_level = 0;
-}
-
-static int     json_level;
-
-static JSObject *
-json_object(const char *s)
-{
-}
-
-static JSArray *
-json_array(const char *s)
-{
-}
-
-static JSString *
-json_string(const char *)
-{
-}
-
-static jsval
-json_number(const char *)
-{
-}
diff --git a/mmsoftware/js/classes/js_cgi.h b/mmsoftware/js/classes/js_cgi.h
deleted file mode 100644 (file)
index 6fa33ba..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id: js_cgi.h,v 1.1 2006/09/08 08:04:58 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSCGI_H
-#define JSCGI_H
-
-#include <jsapi.h>
-
-extern JSObject        *js_InitCGIClass(JSContext *, JSObject *);
-
-#endif
diff --git a/mmsoftware/js/classes/js_dir.c b/mmsoftware/js/classes/js_dir.c
deleted file mode 100644 (file)
index 8e80cc3..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-/* $Id: js_dir.c,v 1.7 2006/10/27 05:38:50 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <sys/types.h>
-
-#include <stdint.h>
-
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-#include <js_dir.h>
-
-
-
-
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-#define SP(n) \
-    { #n, n }
-
-
-
-/*
- * Static prototypes
- */
-static JSBool  dir_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    dir_finalize(JSContext *, JSObject *);
-
-static JSBool  dir_m_read(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  dir_m_tell(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  dir_m_seek(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  dir_m_rewind(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  dir_m_close(JSContext *, JSObject *, uintN, jsval *, jsval *);
-
-static int     dir_path_allow(const char *);
-
-
-
-/*
- * Static globals
- */
-
-/* Dir class */
-static JSClass dir_class = {
-       "Dir", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,
-       JS_ConvertStub, dir_finalize
-};
-
-/* Provided methods */
-static JSFunctionSpec dir_methods[] = {
-       { "read", dir_m_read, 0, 0, 0 },
-       { "tell", dir_m_tell, 0, 0, 0 },
-       { "seek", dir_m_seek, 1, 0, 0 },
-       { "rewind", dir_m_rewind, 0, 0, 0 },
-       { "close", dir_m_close, 0, 0, 0 },
-       { NULL, NULL, 0, 0, 0 },
-};
-
-/* Static properties */
-
-static struct property_spec    dir_sprops[] = {
-       SP(DT_UNKNOWN),
-       SP(DT_FIFO),
-       SP(DT_CHR),
-       SP(DT_DIR),
-       SP(DT_BLK),
-       SP(DT_REG),
-       SP(DT_LNK),
-       SP(DT_SOCK),
-#ifdef DT_WHT
-       SP(DT_WHT),
-#endif
-       { NULL, 0 }
-};
-
-
-
-/*
- * Dir object control
- */
-
-JSObject *
-js_InitDirClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &dir_class, dir_constructor,
-           0, NULL, dir_methods, NULL, NULL)) == NULL) {
-               (void) fprintf(stderr, "Error initializing Dir class\n");
-               goto err;
-       }
-
-       /* Create static properties. */
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "Dir: JS_GetConstructor == NULL\n");
-               return NULL;
-       }
-       for (sp = dir_sprops; sp->name != NULL; sp++) {
-               if (JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT) == JS_FALSE) {
-                       (void) fprintf(stderr,
-                           "Dir: Error defining property %s\n", sp->name);
-                       return NULL;
-               }
-       }
-
-       return proto;
-
-err:
-       return NULL;
-}
-
-static JSBool
-dir_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       DIR     *dir = NULL;
-       char    *path;
-
-       if (!JS_IsConstructing(cx)) {
-               QUEUE_EXCEPTION("Constructor called as a function");
-               goto err;
-       }
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0]) ||
-           ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))) == NULL) {
-               QUEUE_EXCEPTION("Argument not a string");
-               goto err;
-       }
-
-       if (dir_path_allow(path) == -1) {
-               char    str[1024];
-
-               (void) snprintf(str, sizeof(str), "opendir('%s'): %s",
-                   path, "Denied by security hook dir_path_allow()");
-               QUEUE_EXCEPTION(str);
-               goto err;
-       }
-
-       if ((dir = opendir(path)) == NULL) {
-               char    str[1024];
-
-               (void) snprintf(str, sizeof(str), "opendir('%s'): %s",
-                   path, strerror(errno));
-               QUEUE_EXCEPTION(str);
-               goto err;
-       }
-
-       if (!JS_SetPrivate(cx, obj, dir)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (dir != NULL)
-               (void) closedir(dir);
-
-       return JS_FALSE;
-}
-
-static void
-dir_finalize(JSContext *cx, JSObject *obj)
-{
-       DIR     *dir;
-
-       if ((dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL)) != NULL) {
-               (void) closedir(dir);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-}
-
-
-
-/* Methods */
-static JSBool
-dir_m_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       DIR             *dir;
-       struct dirent   *de;
-       JSObject        *o;
-       jsval           val;
-       JSString        *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL);
-       assert(dir != NULL);
-
-       if ((de = readdir(dir)) == NULL) {
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_TRUE;
-       }
-
-       if ((o = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-
-       /* d_fileno is u_int32_t and so could exceed a JS int, so use this */
-       if (!JS_NewNumberValue(cx, (jsdouble)de->d_fileno, &val) ||
-           !JS_DefineProperty(cx, o, "fileno", val, NULL, NULL,
-           JSPROP_ENUMERATE))
-               goto err;
-
-       if (!JS_DefineProperty(cx, o, "type", INT_TO_JSVAL(de->d_type), NULL,
-           NULL, JSPROP_ENUMERATE))
-               goto err;
-
-       /* We can't use d_namlen on Linux
-       if ((str = JS_NewStringCopyN(cx, de->d_name, de->d_namlen)) == NULL ||
-           !JS_DefineProperty(cx, o, "name", STRING_TO_JSVAL(str), NULL,
-           NULL, JSPROP_ENUMERATE))
-               goto err;
-        */
-       if ((str = JS_NewStringCopyZ(cx, de->d_name)) == NULL ||
-           !JS_DefineProperty(cx, o, "name", STRING_TO_JSVAL(str), NULL,
-           NULL, JSPROP_ENUMERATE))
-               goto err;
-
-       return JS_TRUE;
-
-err:
-       QUEUE_EXCEPTION("Internal error!");
-       *rval = OBJECT_TO_JSVAL(NULL);
-       return JS_FALSE;
-}
-
-static JSBool
-dir_m_tell(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       DIR     *dir;
-       long    v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL);
-       assert(dir != NULL);
-
-       v = telldir(dir);
-
-       if (!JS_NewNumberValue(cx, (jsdouble)v, rval)) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-dir_m_seek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       DIR             *dir;
-       jsdouble        v;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_NUMBER(argv[0]) ||
-           !JS_ValueToNumber(cx, argv[0], &v)) {
-               QUEUE_EXCEPTION("Argument 1 not a number");
-               return JS_FALSE;
-       }
-
-       dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL);
-       assert(dir != NULL);
-
-       seekdir(dir, (long)v);
-
-       return JS_TRUE;
-}
-
-static JSBool
-dir_m_rewind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       DIR     *dir;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               return JS_FALSE;
-       }
-
-       dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL);
-       assert(dir != NULL);
-
-       rewinddir(dir);
-
-       return JS_TRUE;
-}
-
-static JSBool
-dir_m_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       DIR     *dir;
-       int     v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       dir = JS_GetInstancePrivate(cx, obj, &dir_class, NULL);
-       assert(dir != NULL);
-
-       v = closedir(dir);
-       *rval = INT_TO_JSVAL(v);
-       (void) JS_SetPrivate(cx, obj, NULL);
-
-       return JS_TRUE;
-}
-
-
-/* Security hook could be added here */
-static int
-dir_path_allow(const char *path)
-{
-
-       return 0;
-}
diff --git a/mmsoftware/js/classes/js_dir.h b/mmsoftware/js/classes/js_dir.h
deleted file mode 100644 (file)
index 9bd504b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id: js_dir.h,v 1.1 2006/09/08 12:50:43 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSDIR_H
-#define JSDIR_H
-
-#include <js_dir.h>
-
-extern JSObject        *js_InitDirClass(JSContext *, JSObject *);
-
-#endif
diff --git a/mmsoftware/js/classes/js_errno.c b/mmsoftware/js/classes/js_errno.c
deleted file mode 100644 (file)
index 829b0b6..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/* $Id: js_errno.c,v 1.2 2006/07/28 02:50:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Basic UNIX errno services for ECMAScript
- */
-
-
-
-#include <sys/types.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-
-
-/* Utility macros */
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-
-/* Prototypes */
-static JSBool  errno_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSBool  errno_sm_strerror(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-
-
-/* Actual class parameters */
-static JSClass errno_class = {
-       "Errno", 0, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
-};
-
-/* Provided static methods */
-static JSFunctionSpec errno_smethods[] = {
-       { "strerror", errno_sm_strerror, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/*
- * Provided static properties.
- * We use these to provide ECMAScript with the ability to use system-specific
- * standard C constant macros without us having to tidiously map them
- * individually, or to require other scripts to be used as headers to define
- * them.  Another possibility would have been to supply these parameters as
- * string, but this would have required even slower remapping because of the
- * parsing and string comparisions.
- * We only include those which we consider necessary for now, others may be
- * added easily as needed, provided that they are added in all three maps.
- * I might perhaps develop macros and/or functions to map all these easily
- * from a single map.
- */
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-#define SP(n) \
-    { #n, n }
-
-static struct property_spec    errno_sprops[] = {
-       SP(EPERM),
-       SP(ENOENT),
-       SP(EINTR),
-       SP(EIO),
-       SP(ENXIO),
-       SP(EBADF),
-       SP(EACCES),
-       SP(ENOTBLK),
-       SP(EBUSY),
-       SP(EEXIST),
-       SP(EXDEV),
-       SP(ENODEV),
-       SP(ENOTDIR),
-       SP(EISDIR),
-       SP(EINVAL),
-       SP(ENFILE),
-       SP(EMFILE),
-       SP(ENOTTY),
-       SP(ETXTBSY),
-       SP(EFBIG),
-       SP(ENOSPC),
-       SP(ESPIPE),
-       SP(EROFS),
-       SP(EMLINK),
-       SP(EPIPE),
-       SP(EAGAIN),
-       SP(EINPROGRESS),
-       SP(EALREADY),
-       SP(ENOTSOCK),
-       SP(EDESTADDRREQ),
-       SP(EMSGSIZE),
-       SP(EPROTOTYPE),
-       SP(EPROTONOSUPPORT),
-       SP(EOPNOTSUPP),
-       SP(EPFNOSUPPORT),
-       SP(EAFNOSUPPORT),
-       SP(EADDRINUSE),
-       SP(EADDRNOTAVAIL),
-       SP(ENETDOWN),
-       SP(ENETUNREACH),
-       SP(ENETRESET),
-       SP(ECONNABORTED),
-       SP(ECONNRESET),
-       SP(ENOBUFS),
-       SP(EISCONN),
-       SP(ENOTCONN),
-       SP(ESHUTDOWN),
-       SP(ETIMEDOUT),
-       SP(ECONNREFUSED),
-       SP(ELOOP),
-       SP(ENAMETOOLONG),
-       SP(EHOSTDOWN),
-       SP(EHOSTUNREACH),
-       SP(ENOTEMPTY),
-       SP(EDQUOT),
-       SP(ESTALE),
-       SP(ENOLCK),
-       SP(ENOSYS),
-       SP(EFTYPE),
-       SP(ENOMSG),
-       SP(ENOTSUP),
-       SP(ECANCELED),
-       SP(EBADMSG),
-       SP(ENODATA),
-       SP(ETIME),
-
-       { NULL, 0 }
-};
-
-#undef SP
-
-
-
-/*
- * Class control functions
- */
-
-JSObject *
-js_InitErrnoClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &errno_class,
-           errno_constructor, 0, NULL, NULL, NULL, errno_smethods)) == NULL) {
-               (void) fprintf(stderr, "Error initializing Errno class\n");
-               return NULL;
-       }
-
-       /* Create static properties */
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "Errno: JS_GetConstructor == NULL\n");
-               return NULL;
-       }
-       for (sp = errno_sprops; sp->name != NULL; sp++) {
-               if (JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT) == JS_FALSE) {
-                       (void) fprintf(stderr,
-                           "Errno: Error defining property %s\n", sp->name);
-                       return NULL;
-               }
-       }
-
-       return proto;
-}
-
-/* ARGSUSED */
-static JSBool
-errno_constructor(JSContext *cx, JSObject *org, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("Errno object not user instanciable");
-
-       return JS_FALSE;
-}
-
-
-/*
- * Static properties functions
- */
-
-
-
-/*
- * Static methods
- */
-
-static JSBool
-errno_sm_strerror(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       int             error;
-       JSString        *string;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(*argv)) {
-               QUEUE_EXCEPTION("Argument not an integer");
-               return JS_FALSE;
-       }
-       error = (int)JSVAL_TO_INT(*argv);
-
-       if ((string = JS_NewStringCopyZ(cx, strerror(error))) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               return JS_FALSE;
-       }
-
-       *rval = STRING_TO_JSVAL(string);
-
-       return JS_TRUE;
-}
diff --git a/mmsoftware/js/classes/js_errno.h b/mmsoftware/js/classes/js_errno.h
deleted file mode 100644 (file)
index c6d7b30..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: js_errno.h,v 1.1 2006/07/22 04:18:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSERRNO_H
-#define JSERRNO_H
-
-extern JSObject        *js_InitErrnoClass(JSContext *, JSObject *);
-
-#endif
diff --git a/mmsoftware/js/classes/js_fd.c b/mmsoftware/js/classes/js_fd.c
deleted file mode 100644 (file)
index fef8fb7..0000000
+++ /dev/null
@@ -1,2120 +0,0 @@
-/* $Id: js_fd.c,v 1.10 2006/09/15 21:04:48 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Basic UNIX filedescriptor and BSD sockets services for ECMAScript
- */
-
-/*
- * XXX TODO XXX
- * - Possibly create a byte buffer type
- * - Add path based restrictions to open()
- * - (maybe) add restrictions to bind()
- * - Either add stat() or provide equivalent properties
- * - Enhance exception reports.  Function name should be provided, and
- *   errno should be displayed when wanted. Perhaps that jsfd->error could
- *   also be set automatically when an exception is generated which involves
- *   errno.
- *   - Check JS_ReportError().
- * - Moving finalizer freeing and close() freeing code to a common function
- *   might be a good idea.
- * - Add getnameinfo()/getaddrinfo() ? Or should we transparently allow this
- *   through properties?
- * - Add send()/sendto()/sendmsg(), recv()/recvfrom()/recvmsg() ...
- * - It is possible that we need to verify that obj is instance of FD in all
- *   methods, perhaps.  I.E. consider an FD method assigned on another object.
- * - Add hostname to address and address to hostname resolution facilities
- * - Maybe also add properties for local end address/port of socket
- * - Would be nice to experiment with a fork(2) heh.  If so, if we allow
- *   fcntl(2) close-on-exec flag, we should make sure to mark FD objects as
- *   closed too for an execve(2) wrapper.
- * - popen(2), would probably need to use custom execve(2) wrapper above...
- * - Add support to easily restrict an application's right to functions.
- *   Path and mode sanity checking functions should also be written and their
- *   parameters set on a per-application basis.
- * - Maybe virtual chdir(2)
- * - A stdio FILE extension object might be nice, with stuff like fdopen() to
- *   create one...  This would be most useful for buffered lined based input
- *   and output.  Exporting mmfd library to js might also be nice perhaps,
- *   either as alternative or addition.
- * - mmap(2) - how could I do this without some byte class and associated
- *   methods?  Seems way tricky.
- * - lstat(2), fstat(2)
- * - dup2()
- * - rename(2), unlink(2) etc would be useful, but we need another class
- *   for this (maybe a VFS static class?)  Maybe even something calling
- *   execve(2) and fork(2), those primitives... popen(3) also.
- * - Also opendir(3) and friends wrapper...
- * - fchdir(2) XXX
- */
-
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <grp.h>
-#include <poll.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <jsapi.h>
-
-#include <js_fd.h>
-
-
-
-/* Utility macros */
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-/* Internal representation of FD object */
-typedef struct jsfd {
-       int     fd;
-       int     type;
-       union   {
-               struct {
-                       char                    *path;
-                       int                     flags;
-                       mode_t                  mode;
-               } file;
-               struct {
-                       int                     domain, type, protocol;
-                       struct sockaddr_in      caddr;
-               } socket;
-       } u;
-       /* For polling; Interesting events, and occurred events */
-       short   events, revents;
-       /* Last error for this descriptor */
-       int     error;
-} jsfd_t;
-
-enum jsfd_types {
-       /* Type */
-       JSFD_NONE =     0,              /* Initial */
-       JSFD_STD =      (1 << 1),
-       JSFD_FILE =     (1 << 2),
-       JSFD_SOCKET =   (1 << 3)
-};
-
-/* Used our fd_sm_poll() function */
-struct poll_fdsi {
-       char    *name;  /* Property name or NULL */
-       jsval   fdobj;  /* Pointer to FD object */
-       jsfd_t  *jsfd;  /* Pointer to FD object data */
-};
-
-struct poll_fds {
-       struct pollfd           *entries;       /* Passed to poll(2) */
-       struct poll_fdsi        *info;
-       int                     count, size;
-};
-
-/* Functions arguments types */
-enum jsarg_types {
-       JSAT_INTEGER =  (1 << 1),
-       JSAT_DOUBLE =   (1 << 2),
-       JSAT_STRING =   (1 << 3),
-       JSAT_OBJECT =   (1 << 4)
-};
-
-
-/* Prototypes */
-static JSBool  fd_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    fd_finalize(JSContext *, JSObject *);
-
-static JSBool  fd_getProperty(JSContext *, JSObject *, jsval, jsval *);
-static JSBool  fd_setProperty(JSContext *, JSObject *, jsval, jsval *);
-
-static JSBool  fd_m_open(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_set(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_close(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_ftruncate(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fd_m_put(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_get(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_socket(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_connect(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_bind(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_listen(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_accept(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_shutdown(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fd_m_setsockopt(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fd_m_getsockopt(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fd_m_fcntl(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_write(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_read(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_fdatasync(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fd_m_lseek(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_fchown(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_fchmod(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_flock(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_fstat(JSContext *, JSObject *, uintN, jsval *, jsval *);
-
-static JSBool  fd_sm_poll(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_sm_poll_mkset(JSContext *, jsval *, jsval *, void *);
-
-static JSBool  object_iterate(JSContext *, JSObject *, void *,
-                   JSBool (*)(JSContext *, jsval *, jsval *, void *));
-static int     fd_path_allow(const char *);
-static mode_t  fd_mode_allow(mode_t);
-static int     fd_flags_allow(int);
-static jsfd_t * fd_methods_args_check(JSContext *, JSObject *, const char *,
-                   int, int, jsval *, int);
-
-
-
-/* Actual class parameters */
-static JSClass fd_class = {
-       "FD", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       fd_getProperty, fd_setProperty, JS_EnumerateStub, JS_ResolveStub,
-       JS_ConvertStub, fd_finalize
-};
-
-enum fd_methods_args_enum {
-       FDMA_SET,
-       FDMA_CLOSE,
-       FDMA_TRUNCATE,
-       FDMA_GET,
-       FDMA_SOCKET,
-       FDMA_CONNECT,
-       FDMA_BIND,
-       FDMA_LISTEN,
-       FDMA_ACCEPT,
-       FDMA_SHUTDOWN,
-       FDMA_SETSOCKOPT,
-       FDMA_GETSOCKOPT,
-       FDMA_FCNTL,
-       FDMA_READ,
-       FDMA_WRITE,
-       FDMA_FDATASYNC,
-       FDMA_LSEEK,
-       FDMA_FCHOWN,
-       FDMA_FCHMOD,
-       FDMA_FLOCK,
-       FDMA_FSTAT,
-       FDMA_FTRUNCATE,
-       FDMA_MAX
-};
-
-static int fd_methods_args_array[FDMA_MAX][6] = {
-       { 1, JSAT_INTEGER },                            /* SET */
-       { 0 },                                          /* CLOSE */
-       { 1, JSAT_DOUBLE | JSAT_INTEGER },              /* TRUNCATE */
-       { 0 },                                          /* GET */
-       { 3, JSAT_INTEGER, JSAT_INTEGER, JSAT_INTEGER },/* SOCKET */
-       { 2, JSAT_STRING, JSAT_INTEGER },               /* CONNECT */
-       { 2, JSAT_STRING, JSAT_INTEGER },               /* BIND */
-       { 1, JSAT_INTEGER },                            /* LISTEN */
-       { 0 },                                          /* ACCEPT */
-       { 1, JSAT_INTEGER },                            /* SHUTDOWN */
-       { 2, JSAT_INTEGER, JSAT_INTEGER },              /* SETSOCKOPT */
-       { 1, JSAT_INTEGER },                            /* GETSOCKOPT */
-       { 2, JSAT_INTEGER, JSAT_INTEGER },              /* FCNTL */
-       { 1, JSAT_INTEGER },                            /* READ */
-       { 1, JSAT_STRING },                             /* WRITE */
-       { 0 },                                          /* FDATASYNC */
-       { 2, JSAT_DOUBLE | JSAT_INTEGER, JSAT_INTEGER },/* LSEEK */
-       { 2, JSAT_STRING | JSAT_INTEGER,
-               JSAT_STRING | JSAT_INTEGER },           /* FCHOWN */
-       { 1, JSAT_INTEGER },                            /* FCHMOD */
-       { 1, JSAT_INTEGER },                            /* FLOCK */
-       { 0 },                                          /* FSTAT */
-       { 1, JSAT_DOUBLE | JSAT_INTEGER },              /* FTRUNCATE */
-};
-
-/* Provided methods/functions */
-static JSFunctionSpec fd_methods[] = {
-       { "open", fd_m_open, 0, 0, 0 }, /* Variable 2-3 parameters */
-       { "set", fd_m_set, 1, 0, 0 },
-       { "close", fd_m_close, 0, 0, 0 },
-       { "ftruncate", fd_m_ftruncate, 1, 0, 0 },
-       { "put", fd_m_put, 1, 0, 0 },
-       { "get", fd_m_get, 0, 0, 0 },
-       { "socket", fd_m_socket, 3, 0, 0 },
-       { "connect", fd_m_connect, 2, 0, 0 },
-       { "bind", fd_m_bind, 2, 0, 0 },
-       { "listen", fd_m_listen, 1, 0, 0 },
-       { "accept", fd_m_accept, 0, 0, 0 },
-       { "shutdown", fd_m_shutdown, 1, 0, 0 },
-       { "setsockopt", fd_m_setsockopt, 2, 0, 0 },
-       { "getsockopt", fd_m_getsockopt, 1, 0, 0 },
-       { "fcntl", fd_m_fcntl, 2, 0, 0 },
-       { "read", fd_m_read, 1, 0, 0 },
-       { "write", fd_m_write, 1, 0, 0 },
-       { "fdatasync", fd_m_fdatasync, 0, 0, 0 },
-       { "lseek", fd_m_lseek, 2, 0, 0 },
-       { "fchown", fd_m_fchown, 2, 0, 0 },
-       { "fchmod", fd_m_fchmod, 1, 0, 0 },
-       { "flock", fd_m_flock, 1, 0, 0 },
-       { "fstat", fd_m_fstat, 0, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/* Provided static methods */
-static JSFunctionSpec fd_smethods[] = {
-       { "poll", fd_sm_poll, 2, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/* Provided properties */
-enum fd_props {
-       FD_P_PATH = 0,
-       FD_P_FD,
-       FD_P_MODE,
-       FD_P_EVENTS,
-       FD_P_REVENTS,
-       FD_P_ERRNO,
-       FD_P_CLIENT_ADDR,
-       FD_P_CLIENT_PORT,
-       FD_P_MAX
-};
-
-static JSPropertySpec fd_properties[FD_P_MAX + 1] = {
-       { "path", FD_P_PATH, JSPROP_ENUMERATE | JSPROP_READONLY, NULL, NULL },
-       { "fd", FD_P_FD, JSPROP_ENUMERATE | JSPROP_READONLY, NULL, NULL },
-       { "mode", FD_P_MODE, JSPROP_ENUMERATE | JSPROP_READONLY, NULL, NULL },
-       { "events", FD_P_EVENTS, JSPROP_ENUMERATE, NULL, NULL },
-       { "revents", FD_P_REVENTS, JSPROP_ENUMERATE | JSPROP_READONLY, NULL,
-           NULL },
-       { "errno", FD_P_ERRNO, JSPROP_ENUMERATE | JSPROP_READONLY, NULL,
-           NULL },
-       { "client_addr", FD_P_CLIENT_ADDR, JSPROP_ENUMERATE | JSPROP_READONLY,
-           NULL, NULL },
-       { "client_port", FD_P_CLIENT_PORT, JSPROP_ENUMERATE | JSPROP_READONLY,
-           NULL, NULL },
-       { NULL, 0, 0, NULL, NULL }
-};
-
-/*
- * Provided static properties.
- * We use these to provide ECMAScript with the ability to use system-specific
- * standard C constant macros without us having to tidiously map them
- * individually, or to require other scripts to be used as headers to define
- * them.  Another possibility would have been to supply these parameters as
- * string, but this would have required even slower remapping because of the
- * parsing and string comparisions.
- * We only include those which we consider necessary for now, others may be
- * added easily as needed, provided that they are added in all three maps.
- * I might perhaps develop macros and/or functions to map all these easily
- * from a single map.
- */
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-#define SP(n) \
-    { #n, n }
-
-static struct property_spec    fd_sprops[] = {
-       SP(STDIN_FILENO),
-       SP(STDOUT_FILENO),
-       SP(STDERR_FILENO),
-
-       SP(O_RDONLY),
-       SP(O_WRONLY),
-       SP(O_RDWR),
-       SP(O_APPEND),
-       SP(O_CREAT),
-       SP(O_TRUNC),
-       SP(O_NONBLOCK),
-
-       SP(POLLIN),
-#ifdef POLLRDNORM
-       SP(POLLRDNORM),
-#endif
-#ifdef POLLRDBAND
-       SP(POLLRDBAND),
-#endif
-       SP(POLLPRI),
-       SP(POLLOUT),
-#ifdef POLLWRNORM
-       SP(POLLWRNORM),
-#endif
-#ifdef POLLWRBAND
-       SP(POLLWRBAND),
-#endif
-       SP(POLLERR),
-       SP(POLLHUP),
-       SP(POLLNVAL),
-
-       SP(SHUT_RD),
-       SP(SHUT_WR),
-       SP(SHUT_RDWR),
-
-       SP(AF_INET),
-       SP(SOCK_STREAM),
-       SP(SOCK_DGRAM),
-
-       SP(SO_REUSEADDR),
-#ifdef SO_REUSEPORT
-       SP(SO_REUSEPORT),
-#endif
-       SP(SO_KEEPALIVE),
-       SP(SO_DONTROUTE),
-       SP(SO_LINGER),
-       SP(SO_BROADCAST),
-       SP(SO_OOBINLINE),
-       SP(SO_SNDBUF),
-       SP(SO_RCVBUF),
-       SP(SO_SNDLOWAT),
-       SP(SO_RCVLOWAT),
-       SP(SO_SNDTIMEO),
-       SP(SO_RCVTIMEO),
-       SP(SO_TIMESTAMP),
-       SP(SO_TYPE),
-       SP(SO_ERROR),
-       SP(TCP_NODELAY),
-
-       SP(F_SETFL),
-       SP(F_GETFL),
-
-       SP(SEEK_SET),
-       SP(SEEK_CUR),
-       SP(SEEK_END),
-
-       SP(S_IRWXU),
-       SP(S_IRUSR),
-       SP(S_IWUSR),
-       SP(S_IXUSR),
-       SP(S_IRWXG),
-       SP(S_IRGRP),
-       SP(S_IXGRP),
-       SP(S_IRWXO),
-       SP(S_IROTH),
-       SP(S_IWOTH),
-       SP(S_IXOTH),
-       SP(S_ISUID),
-       SP(S_ISGID),
-       SP(S_ISVTX),
-       SP(S_IFMT),
-       SP(S_IFIFO),
-       SP(S_IFCHR),
-       SP(S_IFDIR),
-       SP(S_IFBLK),
-       SP(S_IFREG),
-       SP(S_IFLNK),
-       SP(S_IFSOCK),
-#ifdef S_IFWHT
-       SP(S_IFWHT),
-#endif
-#ifdef UF_NODUMP
-       SP(UF_NODUMP),
-#endif
-#ifdef UF_IMMUTABLE
-       SP(UF_IMMUTABLE),
-#endif
-#ifdef UF_APPEND
-       SP(UF_APPEND),
-#endif
-#ifdef UF_OPAQUE
-       SP(UF_OPAQUE),
-#endif
-#ifdef SF_ARCHIVED
-       SP(SF_ARCHIVED),
-#endif
-#ifdef SF_IMMUTABLE
-       SP(SF_IMMUTABLE),
-#endif
-#ifdef SF_APPEND
-       SP(SF_APPEND),
-#endif
-
-       SP(LOCK_SH),
-       SP(LOCK_EX),
-       SP(LOCK_NB),
-       SP(LOCK_UN),
-
-       { NULL, 0 }
-};
-
-#undef SP
-
-
-
-/*
- * Miscelaneous static globals
- */
-
-static int             tcp_proto = 4;
-
-/*
- * These would cause problems with reentrancy.  These buffers should be FD
- * specific to be thread-safe.
- */
-
-/* Read buffer */
-static char            *read_charbuf = NULL;
-static size_t          read_charbuf_size = 0;
-
-/* Poll buffers */
-static struct poll_fds fds = { NULL, NULL, 0, 0 };
-
-
-
-/*
- * Class control functions
- */
-
-JSObject *
-js_InitFDClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &fd_class, fd_constructor,
-           0, fd_properties, fd_methods, NULL, fd_smethods))
-           == NULL) {
-               (void) fprintf(stderr, "Error initializing FD class\n");
-               return NULL;
-       }
-
-       /* Create static properties.  Should probably be a function. */
-
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "FD: JS_GetConstructor == NULL\n");
-               return NULL;
-       }
-       for (sp = fd_sprops; sp->name != NULL; sp++) {
-               if (JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT) == JS_FALSE) {
-                       (void) fprintf(stderr,
-                           "FD: Error defining property %s\n", sp->name);
-                       return NULL;
-               }
-       }
-
-       /* Initialize useful globals for performance */
-       {
-               struct protoent *pent;
-
-               if ((pent = getprotobyname("TCP")) != NULL)
-                       tcp_proto = pent->p_proto;
-       }
-
-       return proto;
-}
-
-static JSBool
-fd_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t  *jsfd = NULL;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       /*
-        * IMPORTANT: We must verify if the caller attempts to execute us as a
-        * normal function rather than as a constructor.  Otherwise, the
-        * caller can cause the interpreter to abort(3) in an assertion in
-        * JS_SetPrivate()!
-        */
-       if (!JS_IsConstructing(cx)) {
-               QUEUE_EXCEPTION("Constructor called as a function");
-               goto err;
-       }
-
-       if ((jsfd = JS_malloc(cx, sizeof(jsfd_t))) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-
-       jsfd->fd = -1;
-       jsfd->type = JSFD_NONE;
-       jsfd->events = jsfd->revents = 0;
-       jsfd->error = 0;
-
-       if (!JS_SetPrivate(cx, obj, jsfd)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (jsfd != NULL)
-               JS_free(cx, jsfd);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-       return JS_FALSE;
-}
-
-static void
-fd_finalize(JSContext *cx, JSObject *obj)
-{
-       jsfd_t  *jsfd;
-
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL)) != NULL) {
-               /* Only close if not one of std descriptors */
-               if (jsfd->fd != -1 && jsfd->type != JSFD_STD) {
-                       (void) close(jsfd->fd);
-                       jsfd->fd = -1;
-                       jsfd->type = JSFD_NONE;
-               }
-               if (jsfd->type == JSFD_FILE && jsfd->u.file.path != NULL) {
-                       JS_free(cx, jsfd->u.file.path);
-                       jsfd->u.file.path = NULL;
-               }
-               JS_free(cx, jsfd);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-}
-
-
-/*
- * Property functions
- */
-
-static JSBool
-fd_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-       jsfd_t  *jsfd;
-       jsint   p;
-
-       if (!JSVAL_IS_INT(id))
-               return JS_TRUE;
-       p = (int)JSVAL_TO_INT(id);
-
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL)) == NULL)
-               return JS_TRUE;
-       if (jsfd->fd == -1)
-               return JS_TRUE;
-
-       switch (p) {
-       case FD_P_PATH:
-               if (jsfd->type == JSFD_FILE) {
-                       JSString        *string;
-
-                       if ((string = JS_NewStringCopyZ(cx,
-                           jsfd->u.file.path)) == NULL) {
-                               QUEUE_EXCEPTION("Out of memory");
-                               return JS_FALSE;
-                       }
-                       *vp = STRING_TO_JSVAL(string);
-               }
-               break;
-       case FD_P_FD:
-               *vp = INT_TO_JSVAL(jsfd->fd);
-               break;
-       case FD_P_MODE:
-               if (jsfd->type == JSFD_FILE)
-                       *vp = INT_TO_JSVAL((int)jsfd->u.file.mode);
-               break;
-       case FD_P_EVENTS:
-               *vp = INT_TO_JSVAL((int)jsfd->events);
-               break;
-       case FD_P_REVENTS:
-               *vp = INT_TO_JSVAL((int)jsfd->revents);
-               break;
-       case FD_P_ERRNO:
-               *vp = INT_TO_JSVAL(jsfd->error);
-               break;
-       case FD_P_CLIENT_ADDR:
-               if (jsfd->type == JSFD_SOCKET) {
-                       char            addr[16];
-                       JSString        *string;
-
-                       if (inet_ntop(AF_INET, &jsfd->u.socket.caddr.sin_addr,
-                           addr, 15) == NULL) {
-                               QUEUE_EXCEPTION(strerror(errno));
-                               return JS_FALSE;
-                       }
-                       if ((string = JS_NewStringCopyZ(cx, addr)) == NULL) {
-                               QUEUE_EXCEPTION("Out of memory");
-                               return JS_FALSE;
-                       }
-                       *vp = STRING_TO_JSVAL(string);
-               }
-               break;
-       case FD_P_CLIENT_PORT:
-               if (jsfd->type == JSFD_SOCKET) {
-                       *vp = INT_TO_JSVAL((int)ntohs(jsfd->
-                           u.socket.caddr.sin_port));
-               }
-               break;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-       jsfd_t  *jsfd;
-       jsint   p;
-
-       if (!JSVAL_IS_INT(id))
-               return JS_TRUE;
-       p = (int)JSVAL_TO_INT(id);
-
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL)) == NULL)
-               return JS_TRUE;
-       if (jsfd->fd == -1)
-               return JS_TRUE;
-
-       switch (p) {
-       case FD_P_EVENTS:
-               if (!JSVAL_IS_INT(*vp)) {
-                       QUEUE_EXCEPTION(
-                           "FD_P_EVENTS property requires an int");
-                       return JS_FALSE;
-               }
-               jsfd->events = (short)JSVAL_TO_INT(*vp);
-               break;
-       }
-
-       return JS_TRUE;
-}
-
-
-/*
- * Static properties functions
- */
-
-
-/*
- * Method functions
- */
-
-static JSBool
-fd_m_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       int             fd, flags;
-       mode_t          mode = 0644;
-       char            *bytes;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       /*
-        * We use custom arguments checking here since we can accept both
-        * 2 or 3.
-        */
-       if (argc < 2 || argc > 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("First argument must be a string");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Second argument must be an integer");
-               return JS_FALSE;
-       }
-       if (argc == 3 && !JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Third argument must be an integer");
-               return JS_FALSE;
-       }
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Null private data!");
-               return JS_FALSE;
-       }
-       if (jsfd->type != JSFD_NONE) {
-               QUEUE_EXCEPTION("Descriptor already open");
-               return JS_FALSE;
-       }
-
-       if (argc == 3) {
-               /*
-                * Mode, supplied as an int.
-                */
-               mode = (mode_t)JSVAL_TO_INT(argv[2]);
-               if ((mode = fd_mode_allow(mode)) == (mode_t)-1) {
-                       QUEUE_EXCEPTION("Mode not permitted");
-                       return JS_FALSE;
-               }
-       }
-
-       /*
-        * Flags, provided as an int.
-        */
-       flags = JSVAL_TO_INT(argv[1]);
-       if ((flags = fd_flags_allow(flags)) == -1) {
-               QUEUE_EXCEPTION("Flag not permitted");
-               return JS_FALSE;
-       }
-
-       /* Path, provided as a string */
-       if ((bytes = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-       /* Perform path sanity checking */
-       if (fd_path_allow(bytes) == -1) {
-               QUEUE_EXCEPTION("Invalid path");
-               return JS_FALSE;
-       }
-       if ((jsfd->u.file.path = JS_strdup(cx, bytes)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               return JS_FALSE;
-       }
-
-       /* We can finally attempt to open(2) */
-       if ((fd = open(bytes, flags, mode)) == -1) {
-               jsfd->error = errno;
-               /*
-                * XXX strerror() seems to always need to load up the
-                * nls table file, which is way silly for performance.
-                * This is related to locale stuff, and should be able
-                * to simply be disabled, even.
-                * Since this event occurs often in httpd.js, let's just
-                * output a fixed string for now.
-                * I should actually fix NetBSD libc on this matter.
-                */
-/*             QUEUE_EXCEPTION(strerror(errno));       */
-               QUEUE_EXCEPTION("open() error");
-               JS_free(cx, jsfd->u.file.path);
-               return JS_FALSE;
-       }
-
-       /* Success! */
-       jsfd->fd = fd;
-       jsfd->type = JSFD_FILE;
-       jsfd->u.file.flags = flags;
-       jsfd->u.file.mode = mode;
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_set(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       int32_t         fd;
-       jsfd_t          *jsfd;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "set", FDMA_SET, argc,
-           argv, JSFD_NONE)) == NULL)
-               return JS_FALSE;
-
-       fd = JSVAL_TO_INT(*argv);
-       /* XXX We now need to allow arbitrary descriptors!
-       if (fd < STDIN_FILENO || fd > STDERR_FILENO) {
-               QUEUE_EXCEPTION("Unknown standard descriptor");
-               return JS_FALSE;
-       }
-       */
-       if (fd == -1) {
-               QUEUE_EXCEPTION("Invalid descriptor (-1)");
-               return JS_FALSE;
-       }
-       jsfd->fd = fd;
-       jsfd->type = JSFD_STD;
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t  *jsfd;
-       int     error;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "close", FDMA_CLOSE, argc,
-           argv, JSFD_STD | JSFD_FILE | JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       if (jsfd->type == JSFD_STD) {
-               jsfd->fd = -1;
-               jsfd->type = JSFD_NONE;
-               return JS_TRUE;
-       }
-
-       if (jsfd->type == JSFD_FILE) {
-               if (jsfd->u.file.path != NULL) {
-                       JS_free(cx, jsfd->u.file.path);
-                       jsfd->u.file.path = NULL;
-               }
-       }
-
-       error = close(jsfd->fd);
-       jsfd->fd = -1;
-       jsfd->type = JSFD_NONE;
-
-       if (error == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_ftruncate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t          *jsfd;
-       off_t           size;
-       jsdouble        dsize;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "truncate", FDMA_TRUNCATE,
-           argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       if (!JS_ValueToNumber(cx, *argv, &dsize)) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-       size = (off_t)dsize;
-
-       if (ftruncate(jsfd->fd, size) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_put(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       JSString        *str;
-       char            *bytes;
-       ssize_t         size;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Null private data!");
-               return JS_FALSE;
-       }
-
-       if (jsfd->fd == -1) {
-               QUEUE_EXCEPTION("Descriptor closed");
-               return JS_FALSE;
-       }
-
-       /*
-        * Instead of verifying if supplied value really is a JSString, and
-        * using JSVAL_TO_STRING(), we convert the value to a string in this
-        * case.
-        */
-       if ((str = JS_ValueToString(cx, *argv)) == NULL ||
-           (bytes = JS_GetStringBytes(str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-
-       size = strlen(bytes);
-       if ((size = write(jsfd->fd, bytes, size)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       *rval = INT_TO_JSVAL((int)size);
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_get(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       char            bytes[4096];
-       ssize_t         size;
-       JSString        *string;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "get", FDMA_GET, argc,
-           argv, JSFD_STD | JSFD_FILE | JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       if ((size = read(jsfd->fd, bytes, 4096)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-       if (size == 0)
-               return JS_TRUE;
-
-       if ((string = JS_NewStringCopyN(cx, bytes, size)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(string);
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_socket(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       int     domain, type, protocol, error;
-       jsfd_t  *jsfd;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "socket", FDMA_SOCKET,
-           argc, argv, JSFD_NONE)) == NULL)
-               return JS_FALSE;
-
-       domain = (int)JSVAL_TO_INT(argv[0]);
-       type = (int)JSVAL_TO_INT(argv[1]);
-       protocol = (int)JSVAL_TO_INT(argv[2]);
-
-       /* Sanity checking on currently supported protocols */
-       if (domain != AF_INET || (type != SOCK_DGRAM && type != SOCK_STREAM)
-           || protocol != 0) {
-               QUEUE_EXCEPTION("Unsupported protocol");
-               return JS_FALSE;
-       }
-
-       if ((error = socket(domain, type, protocol)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       jsfd->fd = error;
-       jsfd->type = JSFD_SOCKET;
-       jsfd->u.socket.domain = domain;
-       jsfd->u.socket.type = type;
-       jsfd->u.socket.protocol = protocol;
-
-       return JS_TRUE;
-}
-
-/*
- * We currently make this rather simple; If the supplied string doesn't
- * consist of a valid IPv4 address, we simply attempt to resolve it, and on
- * success then attempt connection.
- */
-static JSBool
-fd_m_connect(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t                  *jsfd;
-       char                    *address;
-       struct sockaddr_in      sinaddr;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "connect", FDMA_CONNECT,
-           argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       address = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-       if (inet_pton(AF_INET, address, &sinaddr.sin_addr) != 1) {
-               struct hostent  *h;
-
-               /*
-                * Not a valid IPv4 address, consider it as a hostname and
-                * attempt to resolve it.
-                * XXX Note: Not thread safe unless a global mutex/rwlock is
-                * used.  Should use getaddrinfo(3) instead.  Especially if we
-                * someday want to support other address families than
-                * AF_INET.
-                */
-               if ((h = gethostbyname(address)) == NULL) {
-                       jsfd->error = errno;
-                       QUEUE_EXCEPTION("Invalid address or hostname");
-                       return JS_FALSE;
-               }
-               sinaddr.sin_addr.s_addr =
-                   ((struct in_addr *)h->h_addr_list[0])->s_addr;
-       }
-       sinaddr.sin_port = htons((in_port_t)JSVAL_TO_INT(argv[1]));
-       sinaddr.sin_family = AF_INET;
-
-       if (connect(jsfd->fd, (struct sockaddr *)&sinaddr,
-           sizeof(struct sockaddr_in)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_bind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t                  *jsfd;
-       struct sockaddr_in      sinaddr;
-       char                    *address;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "bind", FDMA_BIND, argc,
-           argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       address = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-       if (inet_pton(AF_INET, address, &sinaddr.sin_addr) != 1) {
-               QUEUE_EXCEPTION("Invalid IP address");
-               return JS_FALSE;
-       }
-       sinaddr.sin_port = htons((in_port_t)JSVAL_TO_INT(argv[1]));
-
-       if (bind(jsfd->fd, (struct sockaddr *)&sinaddr,
-           sizeof(struct sockaddr_in)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_listen(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t  *jsfd;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "listen", FDMA_LISTEN,
-           argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       if (listen(jsfd->fd, (int)JSVAL_TO_INT(*argv)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_accept(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t                  *jsfd, *njsfd;
-       int                     sock;
-       struct sockaddr_in      sinaddr;
-       socklen_t               socklen;
-       JSObject                *nobj;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "accept", FDMA_ACCEPT,
-           argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       socklen = sizeof(struct sockaddr_in);
-       if ((sock = accept(jsfd->fd, (struct sockaddr *)&sinaddr, &socklen))
-           == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       /*
-        * Success, create new FD object, fill it and return it.
-        */
-       if ((nobj = JS_ConstructObject(cx, &fd_class, obj, obj)) == NULL) {
-               (void) close(sock);
-               QUEUE_EXCEPTION("Out of resources");
-               return JS_FALSE;
-       }
-       *rval = OBJECT_TO_JSVAL(nobj);
-
-       njsfd = JS_GetInstancePrivate(cx, nobj, &fd_class, NULL);
-       njsfd->fd = sock;
-       njsfd->type = JSFD_SOCKET;
-       njsfd->u.socket.domain = jsfd->u.socket.domain;
-       njsfd->u.socket.type = jsfd->u.socket.type;
-       njsfd->u.socket.protocol = jsfd->u.socket.protocol;
-       (void) memcpy(&njsfd->u.socket.caddr, &sinaddr,
-           sizeof(struct sockaddr_in));
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_shutdown(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t  *jsfd;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "shutdown", FDMA_SHUTDOWN,
-           argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       if (shutdown(jsfd->fd, (int)JSVAL_TO_INT(*argv)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-/*
- * Unlike BSD/POSIX setsockopt(2), always requires a single integer value (-1
- * in the case of SO_LINGER to disable it, or the number of seconds to
- * linger to enable it).
- */
-static JSBool
-fd_m_setsockopt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t          *jsfd;
-       void            *opt;
-       struct linger   l;
-       int             optname, level, optval;
-       socklen_t       optlen;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "setsockopt",
-           FDMA_SETSOCKOPT, argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       optname = JSVAL_TO_INT(argv[0]);
-       optval = JSVAL_TO_INT(argv[1]);
-
-       /*
-        * Work out special case for SO_LINGER
-        */
-       if (optname == SO_LINGER) {
-               if (optval == -1) {
-                       l.l_onoff = 0;
-                       l.l_linger = 0;
-               } else {
-                       l.l_onoff = 1;
-                       l.l_linger = optval;
-               }
-               opt = &l;
-               optlen = sizeof(struct linger);
-       } else {
-               opt = &optval;
-               optlen = sizeof(int);
-               optval = (optval != 0 ? 1 : 0);
-       }
-
-       /*
-        * And for TCP_NODELAY which must use tcp_proto as level
-        */
-       if (optname == TCP_NODELAY)
-               level = tcp_proto;
-       else
-               level = SOL_SOCKET;
-
-       if (setsockopt(jsfd->fd, level, optname, opt, optlen) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-/*
- * Unlike BSD/POSIX getsockopt(2), always returns a single integer value (-1
- * in the case of SO_LINGER disabled, or the number of seconds assigned to
- * wait if enabled).
- */
-static JSBool
-fd_m_getsockopt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t          *jsfd;
-       void            *opt;
-       struct linger   l;
-       int             i, optname, level, result;
-       socklen_t       optlen;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "getsockopt",
-           FDMA_GETSOCKOPT, argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       optname = JSVAL_TO_INT(*argv);
-
-       /*
-        * Special case for SO_LINGER which expects a structure rather than an
-        * integer
-        */
-       if (optname == SO_LINGER) {
-               opt = &l;
-               optlen = sizeof(struct linger);
-       } else {
-               opt = &i;
-               optlen = sizeof(int);
-       }
-
-       /*
-        * And for TCP_NODELAY which must use TCP protocol number rather than
-        * SOL_SOCKET level
-        */
-       if (optname == TCP_NODELAY)
-               level = tcp_proto;
-       else
-               level = SOL_SOCKET;
-
-       if (getsockopt(jsfd->fd, level, optname, opt, &optlen) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       /*
-        * To simplify the implementation, special case of SO_LINGER result;
-        * We return -1 if lingering is disabled, or otherwise return the
-        * number of seconds it should linger for maximum.
-        */
-       if (optname == SO_LINGER) {
-               if (l.l_onoff != 0)
-                       result = l.l_linger;
-               else
-                       result = -1;
-       } else
-               /*
-                * These are booleans, so ensure proper return value despite
-                * several implementations which return a mask rather than 0/1
-                */
-               result = (i != 0 ? 1 : 0);
-
-       *rval = INT_TO_JSVAL(result);
-
-       return JS_TRUE;
-}
-
-/*
- * Unlike POSIX fcntl(2), only currently supports F_GETFL and F_SETFL along
- * with O_NONBLOCK and O_APPEND.  The flags argument is also mandatory, which
- * will serve as a result mask for F_GETFL or to set wanted flags using
- * F_SETFL.  The previous flags are returned as usual (but will only ever
- * include 0, O_NONBLOCK and/or O_APPEND).
- */
-static JSBool
-fd_m_fcntl(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t  *jsfd;
-       int     cmd, flags, error;
-
-       *rval = INT_TO_JSVAL(0);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "fcntl", FDMA_FCNTL,
-           argc, argv, JSFD_FILE | JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       cmd = JSVAL_TO_INT(argv[0]);
-       flags = JSVAL_TO_INT(argv[1]);
-
-       if (cmd != F_GETFL && cmd != F_SETFL) {
-               QUEUE_EXCEPTION("Unimplemented fcntl() command");
-               return JS_FALSE;
-       }
-       flags &= (O_NONBLOCK | O_APPEND);
-       if ((flags & O_NONBLOCK) == 0 && (flags & O_APPEND) == 0) {
-               QUEUE_EXCEPTION("Unimplemented fcntl() flag");
-               return JS_FALSE;
-       }
-
-       if (cmd == F_GETFL) {
-               if ((error = fcntl(jsfd->fd, cmd, NULL)) == -1) {
-                       jsfd->error = errno;
-                       QUEUE_EXCEPTION(strerror(errno));
-                       return JS_FALSE;
-               }
-               error &= flags;
-       } else {
-               if ((error = fcntl(jsfd->fd, cmd, flags)) == -1) {
-                       jsfd->error = errno;
-                       QUEUE_EXCEPTION(strerror(errno));
-                       return JS_FALSE;
-               }
-               error &= (O_NONBLOCK | O_APPEND);
-       }
-
-       *rval = INT_TO_JSVAL(error);
-
-       return JS_TRUE;
-}
-
-/*
- * XXX Not thread-safe as it uses a global read buffer.  To avoid this, read
- * buffers could be FD object specific instead, although this would not be as
- * efficient (in case new FD objects are frequently created), and would
- * require more redundant buffer memory.
- */
-static JSBool
-fd_m_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       size_t          size;
-       ssize_t         rsize;
-       JSString        *string;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "read", FDMA_READ,
-           argc, argv, JSFD_FILE | JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       size = (size_t)JSVAL_TO_INT(*argv);
-       if (size < 1) {
-               QUEUE_EXCEPTION("read() requested size smaller than 1");
-               return JS_FALSE;
-       }
-
-       /*
-        * Ensure that our read buffer is ready, and of a large enough size
-        * to accomodate read.
-        */
-       if (read_charbuf_size < size) {
-               if (read_charbuf == NULL) {
-                       /* Never allocated yet, simply allocate */
-                       if ((read_charbuf = malloc(size)) == NULL) {
-                               QUEUE_EXCEPTION("Cannot allocate read buffer");
-                               return JS_FALSE;
-                       }
-               } else {
-                       char    *ptr;
-
-                       /* Buffer too small, attempt to increase it */
-                       if ((ptr = realloc(read_charbuf, size)) == NULL) {
-                               QUEUE_EXCEPTION(
-                                   "Cannot reallocate read buffer");
-                               return JS_FALSE;
-                       }
-                       read_charbuf = ptr;
-               }
-               read_charbuf_size = size;
-       }
-
-       if ((rsize = read(jsfd->fd, read_charbuf, size)) == -1) {
-               /*
-                * XXX Should we really throw an exception, or simply return
-                * an error?  For instance, if using nonblocking mode and
-                * expecting EAGAIN, would using an exception clubber
-                * unnecessarily the code?
-                */
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-       if (size == 0)
-               return JS_TRUE;
-
-       if ((string = JS_NewStringCopyN(cx, read_charbuf, rsize)) == NULL) {
-               QUEUE_EXCEPTION("Couldn't allocate read result string");
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(string);
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       ssize_t         rsize;
-       JSString        *str;
-       char            *bytes;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "write", FDMA_WRITE,
-           argc, argv, JSFD_FILE | JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       str = JSVAL_TO_STRING(*argv);
-       if ((bytes = JS_GetStringBytes(str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-
-       if ((rsize = write(jsfd->fd, bytes, JS_GetStringLength(str))) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-       *rval = INT_TO_JSVAL((int)rsize);
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_fdatasync(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t          *jsfd;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "fdatasync",
-           FDMA_FDATASYNC, argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       if (fdatasync(jsfd->fd) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_lseek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       off_t           off, newoff;
-       int             whence;
-       jsdouble        doff;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "lseek", FDMA_LSEEK,
-           argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       if (!JS_ValueToNumber(cx, argv[0], &doff)) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-       off = (off_t)doff;
-       whence = JSVAL_TO_INT(argv[1]);
-
-       if ((newoff = lseek(jsfd->fd, off, whence)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       if (!JS_NewDoubleValue(cx, (jsdouble)newoff, rval)) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_fchown(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       struct passwd   *pwd;
-       struct group    *grp;
-       char            *str, e[1024];
-       uid_t           uid;
-       gid_t           gid;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "fchown", FDMA_FCHOWN,
-           argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       if (JSVAL_IS_STRING(argv[0])) {
-               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       return JS_FALSE;
-               }
-               if ((pwd = getpwnam(str)) == NULL) {
-                       (void) snprintf(e, 1023, "Unknown user '%s'", str);
-                       QUEUE_EXCEPTION(e);
-                       return JS_FALSE;
-               }
-               uid = pwd->pw_uid;
-       } else
-               uid = JSVAL_TO_INT(argv[0]);
-
-       if (JSVAL_IS_STRING(argv[1])) {
-               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[1])))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       return JS_FALSE;
-               }
-               if ((grp = getgrnam(str)) == NULL) {
-                       (void) snprintf(e, 1023, "Unknown group '%s'", str);
-                       QUEUE_EXCEPTION(e);
-                       return JS_FALSE;
-               }
-               gid = grp->gr_gid;
-       } else
-               gid = JSVAL_TO_INT(argv[1]);
-
-       if (fchown(jsfd->fd, uid, gid) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_fchmod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       mode_t          mode;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "fchmod", FDMA_FCHMOD,
-           argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       mode = (mode_t)JSVAL_TO_INT(*argv);
-       if ((mode = fd_mode_allow(mode)) == (mode_t)-1) {
-               QUEUE_EXCEPTION("Mode not permitted");
-               return JS_FALSE;
-       }
-
-       if (fchmod(jsfd->fd, mode) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_flock(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       int             op;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "flock", FDMA_FLOCK,
-           argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       op = JSVAL_TO_INT(*argv);
-       if (flock(jsfd->fd, op) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_fstat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       struct stat     st;
-       JSObject        *array = NULL;
-       jsval           val;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "fstat", FDMA_FSTAT,
-           argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       if (fstat(jsfd->fd, &st) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       /*
-        * Note: We immediately link newly created objects to avoid GC
-        * problems.  For the simplicity of this task we don't need an
-        * additional root to be created using JS_AddRoot(), since *rval
-        * is already rooted.  Moreover, the double objects we create are
-        * immediately added as propery as well.
-        */
-
-       if ((array = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(array);
-
-#define DEFINE_INT_PROP(n, i)  do {                                    \
-       val = INT_TO_JSVAL((int)(i));                                   \
-       if (!JS_DefineProperty(cx, array, (n), val, NULL, NULL,         \
-           JSPROP_ENUMERATE)) {                                        \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-#define DEFINE_DOUBLE_PROP(n, d) do {                                  \
-       if (!JS_NewDoubleValue(cx, (jsdouble)(d), &val))                \
-               goto err;                                               \
-       if (!JS_DefineProperty(cx, array, (n), val, NULL, NULL,         \
-           JSPROP_ENUMERATE)) {                                        \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-       DEFINE_INT_PROP("st_dev", st.st_dev);
-       DEFINE_INT_PROP("st_ino", st.st_ino);
-       DEFINE_INT_PROP("st_mode", st.st_mode);
-       DEFINE_INT_PROP("st_nlink", st.st_nlink);
-       DEFINE_INT_PROP("st_uid", st.st_uid);
-       DEFINE_INT_PROP("st_gid", st.st_gid);
-       DEFINE_INT_PROP("st_rdev", st.st_rdev);
-       DEFINE_DOUBLE_PROP("st_atime", st.st_atime);
-       DEFINE_DOUBLE_PROP("st_mtime", st.st_mtime);
-       DEFINE_DOUBLE_PROP("st_ctime", st.st_ctime);
-       DEFINE_DOUBLE_PROP("st_size", st.st_size);
-       DEFINE_DOUBLE_PROP("st_blocks", st.st_blocks);
-       DEFINE_INT_PROP("st_blksize", st.st_blksize);
-       DEFINE_INT_PROP("st_flags", st.st_flags);
-       DEFINE_INT_PROP("st_gen", st.st_gen);
-
-#undef DEFINE_INT_PROP
-#undef DEFINE_DOUBLE_PROP
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-
-/*
- * Static methods
- */
-
-/*
- * XXX Not thread-safe as we are using global buffers.  To avoid this, these
- * buffers would need to be PollSet object specific and we would need to
- * provide such an object with FD add/remove methods.
- */
-static JSBool
-fd_sm_poll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       int             nfds, timeout, i;
-       JSObject        *array = NULL;
-       jsint           index;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       /*
-        * First make sure that user supplied argument really consists of an
-        * object and/or array.
-        */
-       if (!JSVAL_IS_OBJECT(argv[0]) &&
-           !JS_IsArrayObject(cx, JSVAL_TO_OBJECT(argv[0]))) {
-               QUEUE_EXCEPTION("First argument must be Array object");
-               return JS_FALSE;
-       }
-
-       /*
-        * Obtain timeout from argv[1]
-        */
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Second argument must be timeout integer");
-               return JS_FALSE;
-       }
-       timeout = (int)JSVAL_TO_INT(argv[1]);
-
-       /*
-        * Create our pollfd array, iterating through all FD objects of the
-        * user-provided array object.
-        * XXX We ideally should use a buffer which we only need to grow as
-        * necessary, instead of having to reallocate memory every time.
-        * This however would introduce reentrency problems unless we used
-        * this buffer as part of a set object.  We potentially then could
-        * alternatively provide a PollSet object, along with add/remove
-        * methods...
-        */
-       if (fds.entries == NULL && fds.info == NULL) {
-               if ((fds.entries = malloc(sizeof(struct pollfd) * 16))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Out of memory");
-                       goto err;
-               }
-               if ((fds.info = malloc(sizeof(struct poll_fdsi) * 16))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Out of memory");
-                       goto err;
-               }
-               fds.size = 16;
-       }
-       fds.count = 0;
-       if (!object_iterate(cx, JSVAL_TO_OBJECT(argv[0]), &fds,
-           fd_sm_poll_mkset))
-               goto err;
-
-       /*
-        * Finally perform actual polling
-        */
-       if ((nfds = poll(fds.entries, fds.count, timeout)) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               goto err;
-       }
-
-       /*
-        * Now set FD objects event field and create custom array object to
-        * return to the caller, only holding entries for which events
-        * occurred.
-        * Link object immediately to avoid GC problems or needing
-        * JS_AddRoot().
-        */
-       if ((array = JS_NewArrayObject(cx, 0, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(array);
-
-       for (i = 0, index = 0; i < fds.count && nfds != 0; i++) {
-               if (fds.entries[i].revents != 0) {
-                       nfds--;
-                       fds.info[i].jsfd->revents = fds.entries[i].revents;
-                       /*
-                        * Add an element if numeric index entry, or a
-                        * property if name based/associative entry.
-                        */
-                       if (fds.info[i].name == NULL) {
-                               if (!JS_DefineElement(cx, array, index++,
-                                   fds.info[i].fdobj, NULL, NULL,
-                                   JSPROP_ENUMERATE)) {
-                                       QUEUE_EXCEPTION("Internal error!");
-                                       goto err;
-                               }
-                       } else {
-                               if (!JS_DefineProperty(cx, array,
-                                   fds.info[i].name, fds.info[i].fdobj, NULL,
-                                   NULL, JSPROP_ENUMERATE)) {
-                                       QUEUE_EXCEPTION("Internal error!");
-                                       goto err;
-                               }
-                       }
-               }
-       }
-
-       /* We now use global buffers for performance
-       free(fds.entries);
-       free(fds.info);
-       */
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       /* We now use global buffers for performance
-       if (fds.entries != NULL)
-               free(fds.entries);
-       if (fds.info != NULL)
-               free(fds.info);
-        */
-
-       return JS_FALSE;
-}
-
-static JSBool
-fd_sm_poll_mkset(JSContext *cx, jsval *id, jsval *val, void *udata)
-{
-       struct poll_fds *fds = (struct poll_fds *)udata;
-       JSObject        *o;
-       jsfd_t          *jsfd;
-
-       if (!JSVAL_IS_OBJECT(*val) ||
-           !JS_InstanceOf(cx, (o = JSVAL_TO_OBJECT(*val)), &fd_class, NULL)) {
-               QUEUE_EXCEPTION("Not FD object");
-               return JS_FALSE;
-       }
-       if ((jsfd = JS_GetInstancePrivate(cx, o, &fd_class, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Null private data!");
-               return JS_FALSE;
-       }
-
-       if (fds->count == fds->size) {
-               void    *ptr;
-
-               /* Need to grow entries and names */
-               if ((ptr = realloc(fds->entries,
-                   sizeof(struct pollfd) * fds->size * 2)) == NULL) {
-                       QUEUE_EXCEPTION("Out of memory");
-                       return JS_FALSE;
-               }
-               fds->entries = ptr;
-               if ((ptr = realloc(fds->info,
-                   sizeof(struct poll_fdsi) * fds->size * 2)) == NULL) {
-                       QUEUE_EXCEPTION("Out of memory");
-                       return JS_FALSE;
-               }
-               fds->info = ptr;
-               fds->size *= 2;
-       }
-
-       /*
-        * Add new entry.  If it's a property (associative array entry), also
-        * fill in the name pointer which will be used to recreate the result
-        * array with those names as well.  We set the name to NULL for index
-        * based array entries.
-        */
-       fds->entries[fds->count].fd = jsfd->fd;
-       fds->entries[fds->count].events = jsfd->events;
-       fds->entries[fds->count].revents = 0;
-       if (JSVAL_IS_STRING(*id))
-               fds->info[fds->count].name =
-                  JS_GetStringBytes(JSVAL_TO_STRING(*id));
-       else
-               fds->info[fds->count].name = NULL;
-       fds->info[fds->count].fdobj = *val;
-       fds->info[fds->count++].jsfd = jsfd;
-
-       return JS_TRUE;
-}
-
-
-/*
- * Utility functions
- */
-
-/*
- * Was written to be able to iterate over all elements of an array object,
- * despite being an associated array or not, or a mix of both.  Unfortunately
- * uses marked as private JSIdArray structure.
- * This was needed because arrays are using indexes, while associative arrays
- * are nothing more than an object with its properties.  This function can
- * deal with both.
- */
-static JSBool
-object_iterate(JSContext *cx, JSObject *obj, void *udata,
-    JSBool (*func)(JSContext *, jsval *, jsval *, void *))
-{
-       JSIdArray       *a;
-       jsval           id, val;
-       char            *name;
-       jsint           i;
-       JSBool          ret = JS_FALSE;
-
-       if ((a = JS_Enumerate(cx, obj)) != NULL) {
-               for (i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JSVAL_IS_STRING(id)) {
-                               /*
-                                * Property id is a string, attempt to
-                                * lookup its value by name.
-                                */
-                               name = JS_GetStringBytes(JSVAL_TO_STRING(id));
-                               if (!JS_LookupProperty(cx, obj, name, &val))
-                                       continue;
-                       } else {
-                               /*
-                                * Property id is a number, attempt to
-                                * lookup its array element by index.
-                                */
-                               if (!JS_LookupElement(cx, obj,
-                                   JSVAL_TO_INT(id), &val))
-                                               continue;
-                       }
-                       if (!JSVAL_IS_VOID(val)) {
-                               if (!(ret = func(cx, &id, &val, udata)))
-                                       break;
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-       }
-
-       return ret;
-}
-
-/*
- * Utility function return 0 if user supplied path should be allowed, or -1 if
- * it should be rejected (invalid, or permission denied).  This can for
- * instance be used to restrict the program in a virtual chroot(2)-like jail.
- */
-/* ARGSUSED */
-static int
-fd_path_allow(const char *path)
-{
-       /* XXX */
-
-       return 0;
-}
-
-/* ARGSUSED */
-static mode_t
-fd_mode_allow(mode_t mode)
-{
-       /* XXX */
-
-       return mode;
-}
-
-/* ARGSUSED */
-static int
-fd_flags_allow(int flags)
-{
-       /* XXX */
-
-       return flags;
-}
-
-/*
- * Useful to ensure that a function's arguments are as expected, and to
- * retrieve the private data associated with the FD object.  Implemented to
- * minimize code duplication among common functions.
- */
-static jsfd_t *
-fd_methods_args_check(JSContext *cx, JSObject *obj, const char *fun, int id,
-    int argc, jsval *argv, int type)
-{
-       int     *p = fd_methods_args_array[id], i;
-       char    line[1024];
-       jsfd_t  *jsfd;
-
-       if (*p != argc) {
-               (void) snprintf(line, 1023,
-                   "%s() - Wrong number of arguments (%d), expected %d",
-                   fun, argc, *p);
-               QUEUE_EXCEPTION(line);
-               return NULL;
-       }
-
-       for (p++, i = 0; i < argc; i++) {
-               int     cur;
-
-               cur = 0;
-               if (JSVAL_IS_DOUBLE(argv[i]))
-                       cur |= JSAT_DOUBLE;
-               else if (JSVAL_IS_INT(argv[i]))
-                       cur |= JSAT_INTEGER;
-               else if (JSVAL_IS_STRING(argv[i]))
-                       cur |= JSAT_STRING;
-               if ((p[i] & cur) == 0) {
-                       char    types[256];
-
-                       *types = '\0';
-                       if ((p[i] & JSAT_INTEGER) != 0)
-                               (void) strcat(types, "INTEGER | ");
-                       if ((p[i] & JSAT_DOUBLE) != 0)
-                               (void) strcat(types, "DOUBLE | ");
-                       if ((p[i] & JSAT_STRING) != 0)
-                               (void) strcat(types, "STRING | ");
-                       if ((p[i] & JSAT_OBJECT) != 0)
-                               (void) strcat(types, "OBJECT | ");
-                       types[strlen(types) - 3] = '\0';
-                       (void) snprintf(line, 1023,
-                           "%s() - argument #%d not of expected type(s) (%s)",
-                           fun, i + 1, types);
-                       QUEUE_EXCEPTION(line);
-                       return NULL;
-               }
-       }
-
-       /*
-       for (p++, i = 0; i < argc; i++) {
-               switch (p[i]) {
-               case JSAT_INTEGER:
-                       if (!JSVAL_IS_INT(argv[i])) {
-                               (void) snprintf(line, 1023,
-                                   "%s() - argument #%d not an integer",
-                                   fun, i + 1);
-                               QUEUE_EXCEPTION(line);
-                               return NULL;
-                       }
-                       break;
-               case JSAT_DOUBLE:
-                       if (!JSVAL_IS_DOUBLE(argv[i]) &&
-                           !JSVAL_IS_INT(argv[i])) {
-                               (void) snprintf(line, 1023,
-                                   "%s() - argument #%d not a double",
-                                   fun, i + 1);
-                               QUEUE_EXCEPTION(line);
-                               return NULL;
-                       }
-                       break;
-               case JSAT_STRING:
-                       if (!JSVAL_IS_STRING(argv[i])) {
-                               (void) snprintf(line, 1023,
-                                   "%s() - argument #%d not a string",
-                                   fun, i + 1);
-                               QUEUE_EXCEPTION(line);
-                               return NULL;
-                       }
-                       break;
-               default:
-                       (void) snprintf(line, 1023,
-                           "%s() - Unexpected argument type #%d",
-                           fun, i + 1);
-                       QUEUE_EXCEPTION(line);
-                       return NULL;
-               }
-       }
-       */
-
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL))
-           == NULL) {
-               (void) snprintf(line, 1023, "%s() - NULL private data!", fun);
-               QUEUE_EXCEPTION(line);
-               return NULL;
-       }
-
-       if (type == JSFD_NONE && jsfd->type != JSFD_NONE) {
-               (void) snprintf(line, 1023,
-                   "%s() - Descriptor is already open",
-                   fun);
-               QUEUE_EXCEPTION(line);
-               return NULL;
-       } else 
-               return jsfd;
-
-       if ((jsfd->type & type) == 0) {
-               (void) snprintf(line, 1023,
-                   "%s() - Descriptor is closed or of wrong type",
-                   fun);
-               QUEUE_EXCEPTION(line);
-               return NULL;
-       }
-
-       return jsfd;
-}
diff --git a/mmsoftware/js/classes/js_fd.h b/mmsoftware/js/classes/js_fd.h
deleted file mode 100644 (file)
index f0d2f77..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id: js_fd.h,v 1.1 2006/07/22 04:18:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSFD_H
-#define JSFD_H
-
-#include <jsapi.h>
-
-extern JSObject        *js_InitFDClass(JSContext *, JSObject *);
-
-#endif
diff --git a/mmsoftware/js/classes/js_file.c b/mmsoftware/js/classes/js_file.c
deleted file mode 100644 (file)
index 1ca4ac5..0000000
+++ /dev/null
@@ -1,1324 +0,0 @@
-/* $Id: js_file.c,v 1.9 2006/11/26 14:53:00 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Since many libraries support working with FILE * rather than file
- * desdcriptors, it was necessary to provide stdio functionality.
- * The file_new() function is exported so that other modules may create file
- * handles.
- *
- * XXX
- * - add path validity checking hook function
- * - implement formatted printing functions sprintf, fprintf, printf
- * - XXX There is a problem with file_fh().  We probably should provide
- *   a corresponding function to free/unlock the fh.  Because otherwise the
- *   object could be GCed while the FILE * is still being used, causing it
- *   to be unexpectedly closed.  We thus need to root the File object during
- *   the time it's being used by the third party module.  Optionally we could
- *   perhaps leave the responsibility to root the File object to third
- *   parties, but then this isn't always easy obvious since generally it's to
- *   support libraries which deal with FILE *.
- */
-
-
-
-#include <sys/types.h>
-
-#include <stdint.h>
-
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <jsapi.h>
-
-#include <js_file.h>
-
-
-
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-#define SP(n) \
-    { #n, n }
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-enum file_flags {
-       FF_NONE =       0,
-       FF_CLOSE =      (1 << 1),
-       FF_PCLOSE =     (1 << 2)
-};
-
-/*
- * Although we could simply wrap around FILE * directly, we need to know if
- * we should close the file or not upon finalization, and how to close it.
- * We use the flags field for that, since stdio does not allow to associate
- * user data pointers with FILE objects portably (which would have been better
- * for performance).
- */
-typedef struct file {
-       FILE    *fh;
-       int     flags;
-       char    *vbuf;
-       size_t  vbufsize;
-} file_t;
-
-
-
-/*
- * Static prototypes
- */
-
-static JSBool  file_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    file_finalize(JSContext *, JSObject *);
-
-static JSBool  file_sm_popen(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  file_sm_tmpfile(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  file_sm_remove(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  file_sm_strerror(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSBool  file_m_close(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  file_m_reopen(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  file_m_seek(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  file_m_tell(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  file_m_rewind(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  file_m_flush(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  file_m_purge(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  file_m_setvbuf(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  file_m_clearerr(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  file_m_eof(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  file_m_error(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  file_m_fileno(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  file_m_read(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  file_m_write(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  file_m_gets(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  file_m_getc(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  file_m_ungetc(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  file_m_putc(JSContext *, JSObject *, uintN, jsval *, jsval *);
-
-
-
-/*
- * Static globals
- */
-
-/*
- * File
- */
-
-static JSClass file_class = {
-       "File", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,
-       JS_ConvertStub, file_finalize
-};
-
-/* Static properties */
-static struct property_spec    file_sprops[] = {
-       SP(SEEK_SET),
-       SP(SEEK_CUR),
-       SP(SEEK_END),
-       SP(_IONBF),
-       SP(_IOLBF),
-       SP(_IOFBF),
-       SP(STDIN_FILENO),
-       SP(STDOUT_FILENO),
-       SP(STDERR_FILENO),
-       { NULL, 0 }
-};
-
-/* Static methods */
-static JSFunctionSpec file_smethods[] = {
-       { "popen", file_sm_popen, 2, 0, 0 },
-       { "tmpfile", file_sm_tmpfile, 0, 0, 0 },
-       { "remove", file_sm_remove, 1, 0, 0 },
-       { "strerror", file_sm_strerror, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/* Methods */
-static JSFunctionSpec file_methods[] = {
-       { "close", file_m_close, 0, 0, 0 },
-       { "reopen", file_m_reopen, 2, 0, 0 },
-       { "seek", file_m_seek, 2, 0, 0 },
-       { "tell", file_m_tell, 0, 0, 0 },
-       { "rewind", file_m_rewind, 0, 0, 0 },
-       { "flush", file_m_flush, 0, 0, 0 },
-       { "purge", file_m_purge, 0, 0, 0 },
-       { "setvbuf", file_m_setvbuf, 2, 0, 0 },
-       { "clearerr", file_m_clearerr, 0, 0, 0 },
-       { "eof", file_m_eof, 0, 0, 0 },
-       { "error", file_m_error, 0, 0, 0 },
-       { "fileno", file_m_fileno, 0, 0, 0 },
-       { "read", file_m_read, 2, 0, 0 },
-       { "write", file_m_write, 1, 0, 0 },
-       { "gets", file_m_gets, 2, 0, 0 },
-       { "getc", file_m_getc, 1, 0, 0 },
-       { "ungetc", file_m_ungetc, 1, 0, 0 },
-       { "putc", file_m_putc, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/*
- * Static globals.  These could cause reentrancy problems unless they were
- * moved to be File specific, which would however require more RAM and reduce
- * performance.
- */
-static char    *read_charbuf = NULL;
-static size_t  read_charbuf_size = 0;
-
-
-
-/*
- * Publically exported constructor function.  Returns the new File object on
- * success or NULL on failure.
- */
-JSObject *
-file_new(JSContext *cx, FILE *fh, int close)
-{
-       file_t          *f;
-       JSObject        *o;
-
-       assert(fh != NULL);
-
-       if ((f = JS_malloc(cx, sizeof(file_t))) != NULL) {
-               f->fh = fh;
-               f->flags = (close != 0 ? FF_CLOSE : 0);
-               f->vbuf = NULL;
-               f->vbufsize = 0;
-       }
-
-       if ((o = JS_NewObject(cx, &file_class, NULL, NULL)) == NULL)
-               goto err;
-       if (!JS_SetPrivate(cx, o, f))
-               goto err;
-
-       return o;
-
-err:
-       if (f != NULL) {
-               if ((f->flags & FF_CLOSE) != 0 && f->fh != NULL)
-                       (void) fclose(f->fh);
-               JS_free(cx, f);
-       }
-
-       return NULL;
-}
-
-/*
- * Allows external modules to obtain FILE * associated with a File.
- * Returns NULL if not a valid File.
- */
-FILE *
-file_fh(JSContext *cx, jsval v)
-{
-       file_t          *f = NULL;
-       JSObject        *o;
-
-       assert(cx != NULL);
-
-       if (!JSVAL_IS_OBJECT(v))
-               return NULL;
-       o = JSVAL_TO_OBJECT(v);
-       
-       if (!JS_InstanceOf(cx, o, &file_class, NULL))
-               return NULL;
-
-       f = JS_GetInstancePrivate(cx, o, &file_class, NULL);
-       assert(f != NULL);
-
-       return f->fh;
-}
-
-
-
-/*
- * File object control
- */
-
-JSObject *
-js_InitFileClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &file_class, file_constructor,
-           0, NULL, file_methods, NULL, file_smethods)) == NULL) {
-               (void) fprintf(stderr, "Error initializing File class\n");
-               return NULL;
-       }
-
-       /* Create static properties. */
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "File: JS_GetConstructor == NULL\n");
-               return NULL;
-       }
-       for (sp = file_sprops; sp->name != NULL; sp++) {
-               if (JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT) == JS_FALSE) {
-                       (void) fprintf(stderr,
-                           "File: Error defining property %s\n", sp->name);
-                       return NULL;
-               }
-       }
-
-       /* Create stdin, stdout, stderr File objects */
-       {
-               JSObject        *o;
-
-               if ((o = file_new(cx, stdin, 0)) != NULL) {
-                       if (!JS_DefineProperty(cx, obj, "stdin",
-                           OBJECT_TO_JSVAL(o), NULL, NULL,
-                           JSPROP_READONLY | JSPROP_PERMANENT)) {
-                               (void) fprintf(stderr,
-                                   "File: Error defining stdin property\n");
-                               return NULL;
-                       }
-               } else {
-                       (void) fprintf(stderr,
-                           "File: Error creating stdin object\n");
-                       return NULL;
-               }
-
-               if ((o = file_new(cx, stdout, 0)) != NULL) {
-                       if (!JS_DefineProperty(cx, obj, "stdout",
-                           OBJECT_TO_JSVAL(o), NULL, NULL,
-                           JSPROP_READONLY | JSPROP_PERMANENT)) {
-                               (void) fprintf(stderr,
-                                   "File: Error defining stdout property\n");
-                               return NULL;
-                       }
-               } else {
-                       (void) fprintf(stderr,
-                           "File: Error creating stdout object\n");
-                       return NULL;
-               }
-
-               if ((o = file_new(cx, stderr, 0)) != NULL) {
-                       if (!JS_DefineProperty(cx, obj, "stderr",
-                           OBJECT_TO_JSVAL(o), NULL, NULL,
-                           JSPROP_READONLY | JSPROP_PERMANENT)) {
-                               (void) fprintf(stderr,
-                                   "File: Error defining stderr property\n");
-                               return NULL;
-                       }
-               } else {
-                       (void) fprintf(stderr,
-                           "File: Error creating stderr object\n");
-                       return NULL;
-               }
-       }
-
-       return proto;
-}
-
-/*
- * We support a few forms:
- * File(filename:String, mode:String); fopen(3)
- * File(fdnum:Integer, mode:String);   fdopen(3)
- */
-static JSBool
-file_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t          *f = NULL;
-       JSObject        *o;
-
-       if (!JS_IsConstructing(cx)) {
-               QUEUE_EXCEPTION("Constructor called as a function");
-               goto err;
-       }
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       if ((f = JS_malloc(cx, sizeof(file_t))) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       f->flags = 0;
-       f->vbuf = NULL;
-       f->vbufsize = 0;
-
-       if (JSVAL_IS_STRING(argv[0]) && JSVAL_IS_STRING(argv[1])) {
-               char    *path, *mode;
-
-               /* File(filename:String, mode:String); */
-               if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
-                   == NULL ||
-                   (mode = JS_GetStringBytes(JSVAL_TO_STRING(argv[1])))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               f->flags = FF_CLOSE;
-               if ((f->fh = fopen(path, mode)) == NULL) {
-                       QUEUE_EXCEPTION(strerror(errno));
-                       goto err;
-               }
-       } else if (JSVAL_IS_INT(argv[0]) && JSVAL_IS_STRING(argv[1])) {
-               char    *mode;
-
-               /* File(fdnum:Integer, mode:String); */
-               if ((mode = JS_GetStringBytes(JSVAL_TO_STRING(argv[1])))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               f->flags = FF_CLOSE;
-               if ((f->fh = fdopen(JSVAL_TO_INT(argv[0]), mode)) == NULL) {
-                       QUEUE_EXCEPTION(strerror(errno));
-                       goto err;
-               }
-       } else {
-               QUEUE_EXCEPTION("Unknown method (invalid argument types)");
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &file_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if (!JS_SetPrivate(cx, o, f)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (f != NULL) {
-               if ((f->flags & FF_CLOSE) != 0 && f->fh != NULL)
-                       (void) fclose(f->fh);
-               JS_free(cx, f);
-       }
-
-       return JS_FALSE;
-}
-
-/* ARGSUSED */
-static void
-file_finalize(JSContext *cx, JSObject *obj)
-{
-       file_t  *f;
-
-       if ((f = JS_GetInstancePrivate(cx, obj, &file_class, NULL)) != NULL) {
-               if ((f->flags & FF_CLOSE) != 0 && f->fh != NULL) {
-                       if ((f->flags & FF_PCLOSE) != 0)
-                               (void) pclose(f->fh);
-                       else
-                               (void) fclose(f->fh);
-                       if (f->vbuf != NULL)
-                               JS_free(cx, f->vbuf);
-               }
-               (void) JS_SetPrivate(cx, obj, NULL);
-               JS_free(cx, f);
-       }
-}
-
-
-/*
- * File object static methods
- */
-
-static JSBool
-file_sm_popen(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t          *f = NULL;
-       JSObject        *o;
-       char            *cmd, *mode;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not a String");
-               goto err;
-       }
-
-       if ((cmd = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL ||
-           (mode = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       if ((f = JS_malloc(cx, sizeof(file_t))) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       f->flags = FF_CLOSE | FF_PCLOSE;
-       f->vbuf = NULL;
-       f->vbufsize = 0;
-
-       if ((f->fh = popen(cmd, mode)) == NULL) {
-               QUEUE_EXCEPTION(strerror(errno));
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &file_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if (!JS_SetPrivate(cx, o, f)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (f != NULL) {
-               if (f->fh != NULL)
-                       (void) pclose(f->fh);
-               JS_free(cx, f);
-       }
-
-       return JS_FALSE;
-}
-
-static JSBool
-file_sm_tmpfile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t          *f = NULL;
-       JSObject        *o;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       if ((f = JS_malloc(cx, sizeof(file_t))) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       f->flags = FF_CLOSE | FF_PCLOSE;
-       f->vbuf = NULL;
-       f->vbufsize = 0;
-
-       if ((f->fh = tmpfile()) == NULL) {
-               QUEUE_EXCEPTION(strerror(errno));
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &file_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if (!JS_SetPrivate(cx, o, f)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (f != NULL) {
-               if (f->fh != NULL)
-                       (void) fclose(f->fh);
-               JS_free(cx, f);
-       }
-
-       return JS_FALSE;
-}
-
-static JSBool
-file_sm_remove(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       char    *path;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       if (remove(path) != 0) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-/*
- * We allow two forms;  If no arguments are provided, we return the error
- * message associated with errno.  If one is specified, we return the error
- * message associated with the provided error number.
- */
-static JSBool
-file_sm_strerror(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       int             error;
-       JSString        *str;
-
-       if (argc == 0)
-               error = errno;
-       else {
-               if (!JSVAL_IS_INT(argv[0])) {
-                       QUEUE_EXCEPTION("Argument 1 not an Integer");
-                       *rval = OBJECT_TO_JSVAL(NULL);
-                       return JS_FALSE;
-               }
-               error = JSVAL_TO_INT(argv[0]);
-       }
-
-       if ((str = JS_NewStringCopyZ(cx, strerror(error))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-}
-
-
-/*
- * File object methods
- */
-
-static JSBool
-file_m_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t  *f;
-       int     ret;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-
-       if ((f->flags & FF_CLOSE) != 0 && f->fh != NULL) {
-               if ((f->flags & FF_PCLOSE) != 0)
-                       ret = pclose(f->fh);
-               else
-                       ret = fclose(f->fh);
-               f->fh = NULL;
-       } else
-               ret = 0;
-       if (ret == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-file_m_reopen(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t  *f;
-       char    *path, *mode;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not a String");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL ||
-           (mode = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       if ((f->fh = freopen(path, mode, f->fh)) == NULL) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-file_m_seek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       file_t          *f;
-       jsdouble        v;
-       
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_NUMBER(argv[0]) || !JS_ValueToNumber(cx, argv[0], &v)) {
-               QUEUE_EXCEPTION("Argument 1 not a number");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       if (fseeko(f->fh, (off_t)v, JSVAL_TO_INT(argv[1])) != 0) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-file_m_tell(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       file_t          *f;
-       off_t           v;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       if ((v = ftello(f->fh)) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       if (!JS_NewNumberValue(cx, (jsdouble)v, rval)) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-file_m_rewind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t  *f;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       rewind(f->fh);
-
-       return JS_TRUE;
-}
-
-static JSBool
-file_m_flush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t  *f;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       if (fflush(f->fh) != 0) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-file_m_purge(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t  *f;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       if (fpurge(f->fh) != 0) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-/*
- * Unlike stdio setvbuf(3), requires two arguments.  One setting the buffering
- * type, and the other the size of the wanted buffer, or 0 to use the default
- * internal buffer.
- * So our syntax is as follows:  file.setvbuf(type:Integer, bufsize:Integer);
- */
-static JSBool
-file_m_setvbuf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t  *f;
-       size_t  size;
-       char    *vbuf = NULL;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       if ((size = JSVAL_TO_INT(argv[1])) > 0) {
-               if (f->vbuf == NULL) {
-                       if ((f->vbuf = JS_malloc(cx, size)) == NULL) {
-                               QUEUE_EXCEPTION("Out of memory");
-                               return JS_FALSE;
-                       }
-                       f->vbufsize = size;
-                       vbuf = f->vbuf;
-               } else if (size != f->vbufsize) {
-                       if ((vbuf = JS_realloc(cx, f->vbuf, size)) == NULL) {
-                               QUEUE_EXCEPTION("Out of memory");
-                               return JS_FALSE;
-                       }
-                       f->vbuf = vbuf;
-                       f->vbufsize = size;
-               }
-       }
-
-       if (setvbuf(f->fh, vbuf, JSVAL_TO_INT(argv[0]), size) != 0) {
-               QUEUE_EXCEPTION("setvbuf() == EOF");
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-file_m_clearerr(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t  *f;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-       
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       clearerr(f->fh);
-
-       return JS_TRUE;
-}
-
-static JSBool
-file_m_eof(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       file_t  *f;
-       int     v;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-       
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       v = feof(f->fh);
-       *rval = BOOLEAN_TO_JSVAL((JSBool)v);
-
-       return JS_TRUE;
-}
-
-static JSBool
-file_m_error(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t  *f;
-       int     v;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-       
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       v = ferror(f->fh);
-       *rval = BOOLEAN_TO_JSVAL((JSBool)v);
-
-       return JS_TRUE;
-}
-
-static JSBool
-file_m_fileno(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t  *f;
-       int     v;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       v = fileno(f->fh);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-}
-
-/*
- * Unlike fread(3), returns a string holding the read buffer (which could also
- * be shorter than requested), or throws an exception on error.
- */
-static JSBool
-file_m_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       file_t          *f;
-       size_t          size, nmemb, tsize, rsize;
-       JSString        *str;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-       size = JSVAL_TO_INT(argv[0]);
-       nmemb = JSVAL_TO_INT(argv[1]);
-       tsize = size * nmemb;
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       /*
-        * Ensure that read buffer is ready and large enough
-        */
-       if (read_charbuf_size < tsize) {
-               if (read_charbuf == NULL) {
-                       if ((read_charbuf = malloc(tsize)) == NULL) {
-                               QUEUE_EXCEPTION("Cannot allocate read buffer");
-                               return JS_FALSE;
-                       }
-               } else {
-                       char    *ptr;
-
-                       if ((ptr = realloc(read_charbuf, tsize)) == NULL) {
-                               QUEUE_EXCEPTION(
-                                   "Cannot reallocate read bufer");
-                               return JS_FALSE;
-                       }
-                       read_charbuf = ptr;
-               }
-               read_charbuf_size = tsize;
-       }
-
-       if ((rsize = fread(read_charbuf, size, nmemb, f->fh)) != nmemb) {
-               if (rsize == 0) {
-                       QUEUE_EXCEPTION(strerror(errno));
-                       return JS_FALSE;
-               }
-       }
-
-       if ((str = JS_NewStringCopyN(cx, read_charbuf, rsize * size))
-           == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-}
-
-/*
- * Unlike fwrite(2), is simply provided the string to write rather than having
- * to specify sizes.
- */
-static JSBool
-file_m_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t          *f;
-       JSString        *str;
-       char            *bytes;
-       size_t          size;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       str = JSVAL_TO_STRING(argv[0]);
-       if ((bytes = JS_GetStringBytes(str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       size = JS_GetStringLength(str);
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       if (fwrite(bytes, size, 1, f->fh) != 1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-/*
- * Like fgets(3), is provided a maximum buffer size (which although is
- * internal).  Automatically strips the '\r', '\n' or '\r\n' if the second
- * argument is false, or keep them otherwise.  On error, we throw an
- * exception.
- */
-static JSBool
-file_m_gets(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       file_t          *f;
-       size_t          tsize;
-       JSBool          nostrip;
-       JSString        *str;
-       char            *rstr;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_BOOLEAN(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not a Boolean");
-               return JS_FALSE;
-       }
-       tsize = JSVAL_TO_INT(argv[0]);
-       nostrip = JSVAL_TO_BOOLEAN(argv[1]);
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       /*
-        * Ensure that read buffer is ready and large enough
-        */
-       if (read_charbuf_size < tsize) {
-               if (read_charbuf == NULL) {
-                       if ((read_charbuf = malloc(tsize)) == NULL) {
-                               QUEUE_EXCEPTION("Cannot allocate read buffer");
-                               return JS_FALSE;
-                       }
-               } else {
-                       char    *ptr;
-
-                       if ((ptr = realloc(read_charbuf, tsize)) == NULL) {
-                               QUEUE_EXCEPTION(
-                                   "Cannot reallocate read bufer");
-                               return JS_FALSE;
-                       }
-                       read_charbuf = ptr;
-               }
-               read_charbuf_size = tsize;
-       }
-
-       if ((rstr = fgets(read_charbuf, tsize, f->fh)) == NULL) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-       tsize = strlen(rstr);
-
-       if ((str = JS_NewStringCopyN(cx, rstr, tsize)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-}
-
-/*
- * Returns an int just like fgetc(3) but throws an exception on error.
- */
-static JSBool
-file_m_getc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       file_t  *f;
-       int     c;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       if ((c = fgetc(f->fh)) == EOF) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-       *rval = INT_TO_JSVAL(c);
-
-       return JS_TRUE;
-}
-
-/*
- * Like ungetc(3) but throws an exception on error.
- */
-static JSBool
-file_m_ungetc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       file_t  *f;
-       int     c;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       if ((c = ungetc(JSVAL_TO_INT(argv[0]), f->fh)) == EOF) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-       *rval = INT_TO_JSVAL(c);
-
-       return JS_TRUE;
-}
-
-/*
- * Works with an int just like fputc(3).  Throws an exception on error.
- */
-static JSBool
-file_m_putc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       file_t  *f;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-
-       f = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
-       assert(f != NULL);
-       if (f->fh == NULL) {
-               QUEUE_EXCEPTION("File already closed");
-               return JS_FALSE;
-       }
-
-       if (fputc(JSVAL_TO_INT(argv[0]), f->fh) != 0) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
diff --git a/mmsoftware/js/classes/js_file.h b/mmsoftware/js/classes/js_file.h
deleted file mode 100644 (file)
index c6d18c2..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* $Id: js_file.h,v 1.3 2006/09/26 11:49:49 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSFILE_H
-#define JSFILE_H
-
-#include <js_file.h>
-
-extern JSObject        *js_InitFileClass(JSContext *, JSObject *);
-
-extern JSObject        *file_new(JSContext *, FILE *, int);
-extern FILE    *file_fh(JSContext *, jsval);
-
-#endif
diff --git a/mmsoftware/js/classes/js_fs.c b/mmsoftware/js/classes/js_fs.c
deleted file mode 100644 (file)
index 8e46534..0000000
+++ /dev/null
@@ -1,873 +0,0 @@
-/* $Id: js_fs.c,v 1.3 2006/10/27 05:41:30 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <stdint.h>
-
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <grp.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <jsapi.h>
-
-#include <js_fs.h>
-
-
-
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-
-/*
- * Static prototypes
- */
-static JSBool  fs_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    fs_finalize(JSContext *, JSObject *);
-
-static JSBool  fs_sm_chdir(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_getcwd(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_mkdir(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_rmdir(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_stat(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_lstat(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_chown(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_lchown(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_chmod(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_rename(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_unlink(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fs_sm_truncate(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fs_sm_creat(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_mknod(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_mkfifo(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fs_sm_symlink(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSBool  fs_sm_stat_i(JSContext *, JSObject *, uintN, jsval *, jsval *,
-                   int (*)(const char *, struct stat *));
-
-static int     chown_resolve(JSContext *, jsval, jsval, uid_t *, gid_t *);
-
-static mode_t  fs_mode_allow(mode_t);
-static int     fs_path_allow(const char *);
-
-
-
-/*
- * Static globals
- */
-
-/* FS class */
-static JSClass fs_class = {
-       "FS", 0, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,
-       JS_ConvertStub, fs_finalize
-};
-
-/* Provided static methods */
-static JSFunctionSpec fs_smethods[] = {
-       { "chdir", fs_sm_chdir, 1, 0, 0 },
-       { "getcwd", fs_sm_getcwd, 0, 0, 0 },
-       { "mkdir", fs_sm_mkdir, 2, 0, 0 },
-       { "rmdir", fs_sm_rmdir, 1, 0, 0 },
-       { "stat", fs_sm_stat, 1, 0, 0 },
-       { "lstat", fs_sm_lstat, 1, 0, 0 },
-       { "chown", fs_sm_chown, 3, 0, 0 },
-       { "lchown", fs_sm_lchown, 3, 0, 0 },
-       { "chmod", fs_sm_chmod, 2, 0, 0 },
-       { "rename", fs_sm_rename, 2, 0, 0 },
-       { "unlink", fs_sm_unlink, 1, 0, 0 },
-       { "truncate", fs_sm_truncate, 2, 0, 0 },
-       { "creat", fs_sm_creat, 2, 0, 0 },
-       { "mknod", fs_sm_mknod, 3, 0, 0 },
-       { "mkfifo", fs_sm_mkfifo, 2, 0, 0 },
-       { "symlink", fs_sm_symlink, 2, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-
-
-/*
- * FS object control
- */
-
-JSObject *
-js_InitFSClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &fs_class, fs_constructor,
-           0, NULL, NULL, NULL, fs_smethods)) == NULL)
-               (void) fprintf(stderr, "Error initializing FS class\n");
-
-       return proto;
-}
-
-static JSBool
-fs_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("FS class non-instanciable");
-
-       return JS_FALSE;
-}
-
-static void
-fs_finalize(JSContext *cx, JSObject *obj)
-{
-
-       /* NOOP */
-}
-
-
-
-/* Static methods */
-static JSBool
-fs_sm_chdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       char    *path;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       if (fs_path_allow(path) == -1) {
-               QUEUE_EXCEPTION("Path not allowed");
-               return JS_FALSE;
-       }
-
-       if (chdir(path) != 0) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_getcwd(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       static char     cwd[MAXPATHLEN];
-       JSString        *str;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       if (getcwd(cwd, MAXPATHLEN - 1) == NULL) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       if ((str = JS_NewStringCopyZ(cx, cwd)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_mkdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       char    *path;
-       mode_t  mode;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path) != 0) {
-               QUEUE_EXCEPTION("Path not allowed");
-               return JS_FALSE;
-       }
-
-       mode = fs_mode_allow((mode_t)JSVAL_TO_INT(argv[1]));
-
-       if (mkdir(path, mode) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_rmdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       char    *path;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path) != 0) {
-               QUEUE_EXCEPTION("Path not allowed");
-               return JS_FALSE;
-       }
-
-       if (rmdir(path) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_stat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-
-       return fs_sm_stat_i(cx, obj, argc, argv, rval, stat);
-}
-
-static JSBool
-fs_sm_lstat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-
-       return fs_sm_stat_i(cx, obj, argc, argv, rval, lstat);
-}
-
-static JSBool
-fs_sm_chown(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       char    *path;
-       uid_t   uid;
-       gid_t   gid;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path) != 0) {
-               QUEUE_EXCEPTION("Path not allowed");
-               return JS_FALSE;
-       }
-
-       if (chown_resolve(cx, argv[1], argv[2], &uid, &gid) == -1)
-               return JS_FALSE;
-
-       if (chown(path, uid, gid) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_lchown(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       char    *path;
-       uid_t   uid;
-       gid_t   gid;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path) != 0) {
-               QUEUE_EXCEPTION("Path not allowed");
-               return JS_FALSE;
-       }
-
-       if (chown_resolve(cx, argv[1], argv[2], &uid, &gid) == -1)
-               return JS_FALSE;
-
-       if (lchown(path, uid, gid) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_chmod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       char    *path;
-       mode_t  mode;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path) != 0) {
-               QUEUE_EXCEPTION("Path not allowed");
-               return JS_FALSE;
-       }
-
-       mode = fs_mode_allow((mode_t)JSVAL_TO_INT(argv[1]));
-
-       if (chmod(path, mode) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_rename(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       char    *path1, *path2;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not a String");
-               return JS_FALSE;
-       }
-
-       if ((path1 = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path1) != 0) {
-               QUEUE_EXCEPTION("Path 1 not allowed");
-               return JS_FALSE;
-       }
-
-       if ((path2 = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path2) != 0) {
-               QUEUE_EXCEPTION("Path 2 not allowed");
-               return JS_FALSE;
-       }
-
-       if (rename(path1, path2) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_unlink(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       char    *path;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path) != 0) {
-               QUEUE_EXCEPTION("Path not allowed");
-               return JS_FALSE;
-       }
-
-       if (unlink(path) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_truncate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       char            *path;
-       off_t           size;
-       jsdouble        dsize;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_NUMBER(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not a number");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path) != 0) {
-               QUEUE_EXCEPTION("Path not allowed");
-               return JS_FALSE;
-       }
-
-       if (!JS_ValueToNumber(cx, argv[1], &dsize)) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       size = (off_t)dsize;
-
-       if (truncate(path, size) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_creat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       char    *path;
-       mode_t  mode;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path) != 0) {
-               QUEUE_EXCEPTION("Path not allowed");
-               return JS_FALSE;
-       }
-
-       mode = fs_mode_allow((mode_t)JSVAL_TO_INT(argv[1]));
-
-       if (creat(path, mode) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_mknod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       char    *path;
-       mode_t  mode;
-       dev_t   dev;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path) != 0) {
-               QUEUE_EXCEPTION("Path not allowed");
-               return JS_FALSE;
-       }
-
-       mode = fs_mode_allow((mode_t)JSVAL_TO_INT(argv[1]));
-
-       dev = (dev_t)JSVAL_TO_INT(argv[2]);
-
-       if (mknod(path, mode, dev) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_mkfifo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       char    *path;
-       mode_t  mode;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path) != 0) {
-               QUEUE_EXCEPTION("Path not allowed");
-               return JS_FALSE;
-       }
-
-       mode = fs_mode_allow((mode_t)JSVAL_TO_INT(argv[1]));
-
-       if (mkfifo(path, mode) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fs_sm_symlink(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       char    *path1, *path2;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not a String");
-               return JS_FALSE;
-       }
-
-       if ((path1 = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path1) != 0) {
-               QUEUE_EXCEPTION("Path 1 not allowed");
-               return JS_FALSE;
-       }
-
-       if ((path2 = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (fs_path_allow(path2) != 0) {
-               QUEUE_EXCEPTION("Path 2 not allowed");
-               return JS_FALSE;
-       }
-
-       if (symlink(path1, path2) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-
-static JSBool
-fs_sm_stat_i(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, int (*stat_i)(const char *, struct stat *))
-{
-       char            *path;
-       struct stat     st;
-       JSObject        *o = NULL;
-       jsval           val;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-
-       if ((path = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       if (fs_path_allow(path) == -1) {
-               QUEUE_EXCEPTION("Path now allowed");
-               return JS_FALSE;
-       }
-
-       if (stat_i(path, &st) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       /*
-        * Note: We immediately link newly created objects to avoid GC
-        * problems.  For the simplicity of this task we don't need an
-        * additional root to be created using JS_AddRoot(), since *rval
-        * is already rooted.  Moreover, the double objects we create are
-        * immediately added as propery as well.
-        */
-
-       if ((o = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-
-#define DEFINE_INT_PROP(n, i)  do {                                    \
-       val = INT_TO_JSVAL((int)(i));                                   \
-       if (!JS_DefineProperty(cx, o, (n), val, NULL, NULL,             \
-           JSPROP_ENUMERATE)) {                                        \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-#define DEFINE_DOUBLE_PROP(n, d) do {                                  \
-       if (!JS_NewDoubleValue(cx, (jsdouble)(d), &val))                \
-               goto err;                                               \
-       if (!JS_DefineProperty(cx, o, (n), val, NULL, NULL,             \
-           JSPROP_ENUMERATE)) {                                        \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-       DEFINE_INT_PROP("st_dev", st.st_dev);
-       DEFINE_INT_PROP("st_ino", st.st_ino);
-       DEFINE_INT_PROP("st_mode", st.st_mode);
-       DEFINE_INT_PROP("st_nlink", st.st_nlink);
-       DEFINE_INT_PROP("st_uid", st.st_uid);
-       DEFINE_INT_PROP("st_gid", st.st_gid);
-       DEFINE_INT_PROP("st_rdev", st.st_rdev);
-       DEFINE_DOUBLE_PROP("st_atime", st.st_atime);
-       DEFINE_DOUBLE_PROP("st_mtime", st.st_mtime);
-       DEFINE_DOUBLE_PROP("st_ctime", st.st_ctime);
-       DEFINE_DOUBLE_PROP("st_size", st.st_size);
-       DEFINE_DOUBLE_PROP("st_blocks", st.st_blocks);
-       DEFINE_INT_PROP("st_blksize", st.st_blksize);
-       DEFINE_INT_PROP("st_flags", st.st_flags);
-       DEFINE_INT_PROP("st_gen", st.st_gen);
-
-#undef DEFINE_INT_PROP
-#undef DEFINE_DOUBLE_PROP
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-
-static int
-chown_resolve(JSContext *cx, jsval vuid, jsval vgid, uid_t *uid, gid_t *gid)
-{
-       char            *str, e[1024];
-       struct passwd   *pwd;
-       struct group    *grp;
-
-       if (JSVAL_IS_STRING(vuid)) {
-               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(vuid))) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       return -1;
-               }
-               if ((pwd = getpwnam(str)) == NULL) {
-                       (void) snprintf(e, 1023, "Unknown user '%s'", str);
-                       QUEUE_EXCEPTION(e);
-                       return -1;
-               }
-               *uid = pwd->pw_uid;
-       } else if (JSVAL_IS_INT(vuid))
-               *uid = JSVAL_TO_INT(vuid);
-       else {
-               QUEUE_EXCEPTION("uid argument not String or Integer");
-               return -1;
-       }
-
-       if (JSVAL_IS_STRING(vgid)) {
-               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(vgid))) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       return -1;
-               }
-               if ((grp = getgrnam(str)) == NULL) {
-                       (void) snprintf(e, 1023, "Unknown group '%s'", str);
-                       QUEUE_EXCEPTION(e);
-                       return -1;
-               }
-               *gid = grp->gr_gid;
-       } else if (JSVAL_IS_INT(vgid))
-               *gid = JSVAL_TO_INT(vgid);
-       else {
-               QUEUE_EXCEPTION("gid argument not String or Integer");
-               return -1;
-       }
-
-       return 0;
-}
-
-static mode_t
-fs_mode_allow(mode_t mode)
-{
-       /* XXX */
-
-       return mode;
-}
-
-/* ARGSUSED */
-static int
-fs_path_allow(const char *path)
-{
-       /* XXX */
-
-       return 0;
-}
diff --git a/mmsoftware/js/classes/js_fs.h b/mmsoftware/js/classes/js_fs.h
deleted file mode 100644 (file)
index 3785dc2..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: js_fs.h,v 1.1 2006/09/15 21:04:48 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSFS_H
-#define JSFS_H
-
-extern JSObject        *js_InitFSClass(JSContext *, JSObject *);
-
-#endif
diff --git a/mmsoftware/js/classes/js_gcroot.c b/mmsoftware/js/classes/js_gcroot.c
deleted file mode 100644 (file)
index 194d550..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-/* $Id: js_gcroot.c,v 1.3 2006/10/18 05:07:42 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * This module provides APIs to several tricks which may be required to
- * support the functionality of a few C libraries when writing their JS stubs.
- * Here are cases where it can be useful:
- *
- * - An object must be provided to a C library for an arbitrary amount of time
- *   and we must ensure that it does not get freed by the potential
- *   auto-destruction of the object by the garbage collector.
- *   An example of this is in js_pgsql.c where PQtrace() can be provided a
- *   FILE *.  We thus can store the wrapping File object as a property into
- *   the context-global rooted GCRoot object, and delete it from the object
- *   when PQuntrace() is called.
- *   An application using this functionality must call js_InitGCRoot() when
- *   creating contexts and js_DestroyGCRoot() before destroying the contexts.
- *   It may then call js_GCRoot() to obtain the JSObject pointer of the rooted
- *   object to assiciate properties with.  Since this clobbers the private
- *   data which can be set for a context using JS_SetContextPrivate(),
- *   alternate functions are provided to store arbitrary context-specific
- *   data: js_GCRoot_udata_set()/js_GCRoot_udata_get().
- * - A C API function must be provided an object which is internally wrapped
- *   by a JSObject, but to which it is impossibe to pass the JSContext * and
- *   JSObject *.  There must then be a way to map internal arbitrary C
- *   pointers to their corresponding JSContext/JSObject pointers, in which
- *   case we may use the js_map_add() function at object construction and
- *   js_map_remove() at its destruction, and js_map_lookup() to obtain the
- *   necessary information from within the C function.  This case most often
- *   occurs for callback functions, like for the notice receiver callback
- *   in js_pgsql.c.
- *   To use this functionality, the application must call js_map_init() after
- *   creating the runtime, and js_map_destroy() before destroying the runtime.
- *   Provision is also made to store an additional user data pointer.
- * - In cases where the private data set on an object also must hold the
- *   JSContext * and JSObject * associated with it, it is possible to use
- *   the js_udata_alloc() and js_udata_free() to create/destroy private
- *   data objects.  Additionally, udata_t also allows to store more than one
- *   void *, which may be useful.
- */
-
-
-
-#include <sys/types.h>
-
-#include <stdint.h>
-
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-#include <js_gcroot.h>
-
-
-
-/*
- * We define a structure allowing to continue storing context-specific
- * user-data, while also storing the gcroot which requires a unique address in
- * the process space (and can't be on the stack) to be rooted.
- */
-typedef struct cxspec {
-       JSObject        *gcroot;
-       udata_t         *udata;
-} cxspec_t;
-
-
-
-/*
- * Static functions prototypes
- */
-static int             omap_keycmp(const void *, const void *, size_t);
-static u_int32_t       omap_keyhash(const void *, size_t);
-
-
-
-/*
- * Static globals
- */
-
-/* Dir class */
-static JSClass gcroot_class = {
-       "GCRoot", 0, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
-       JS_FinalizeStub
-};
-
-/*
- * XXX since these are runtime-global, they should be lock-protected if we
- * wanted thread-safe code.
- */
-static pool_t          udata_pool;
-static pool_t          omap_pool;
-static hashtable_t     omap_table;
-
-
-
-/*
- * GCRoot object control
- */
-
-JSBool
-js_InitGCRoot(JSContext *cx)
-{
-       cxspec_t        *d = NULL;
-
-       if ((d = malloc(sizeof(cxspec_t))) == NULL) {
-               (void) fprintf(stderr, "GCRoot: malloc()\n");
-               return JS_FALSE;
-       }
-       d->udata = NULL;
-
-       /* Instantiate new object */
-       if ((d->gcroot = JS_NewObject(cx, &gcroot_class, NULL, NULL))
-           == NULL) {
-               (void) fprintf(stderr, "GCRoot: JS_NewObject(gcroot)\n");
-               goto err;
-       }
-       if (!JS_AddRoot(cx, &d->gcroot)) {
-               (void) fprintf(stderr, "GCRoot: JS_AddRoot(gcroot)\n");
-               goto err;
-       }
-       JS_SetContextPrivate(cx, d);
-
-       return JS_TRUE;
-
-err:
-       if (d != NULL)
-               free(d);
-
-       return JS_FALSE;
-}
-
-void
-js_DestroyGCRoot(JSContext *cx)
-{
-       cxspec_t        *d;
-
-       if ((d = JS_GetContextPrivate(cx)) != NULL) {
-               assert(d->udata == NULL);
-               if (d->gcroot != NULL) {
-                       if (!JS_RemoveRoot(cx, &d->gcroot))
-                               (void) fprintf(stderr,
-                                   "GCRoot: JS_RemoveRoot(gcroot)\n");
-               }
-               free(d);
-               JS_SetContextPrivate(cx, NULL);
-       }
-}
-
-JSObject *
-js_GCRoot(JSContext *cx)
-{
-       cxspec_t        *d;
-
-       d = JS_GetContextPrivate(cx);
-       assert(d != NULL);
-
-       return d->gcroot;
-}
-
-void
-js_GCRoot_udata_set(JSContext *cx, udata_t *udata)
-{
-       cxspec_t        *d;
-
-       d = JS_GetContextPrivate(cx);
-       assert(d != NULL);
-
-       d->udata = udata;
-}
-
-udata_t *
-js_GCRoot_udata_get(JSContext *cx)
-{
-       cxspec_t        *d;
-
-       d = JS_GetContextPrivate(cx);
-       assert(d != NULL);
-
-       return d->udata;
-}
-
-udata_t *
-js_udata_alloc(JSContext *cx, JSObject *obj)
-{
-       udata_t *udata;
-
-       if ((udata = (udata_t *)pool_alloc(&udata_pool, FALSE)) != NULL) {
-               int     i;
-
-               udata->cx = cx;
-               udata->obj = obj;
-               for (i = 0; i < UDATA_MAX; )
-                       udata->udata[i++] = NULL;
-       }
-
-       return udata;
-}
-
-void
-js_udata_free(udata_t *udata)
-{
-
-       (void) pool_free((pnode_t *)udata);
-}
-
-
-JSBool
-js_map_init(void)
-{
-
-       if (!pool_init(&udata_pool, "udata_pool", malloc, free, NULL, NULL,
-           sizeof(udata_t), 64, 1, 0))
-               goto err;
-
-       if (!pool_init(&omap_pool, "omap_pool", malloc, free, NULL, NULL,
-           sizeof(omap_t), 64, 1, 0))
-               goto err;
-
-       if (!hashtable_init(&omap_table, "omap_table", HT_DEFAULT_CAPACITY,
-           HT_DEFAULT_FACTOR, malloc, free, omap_keycmp, omap_keyhash, TRUE))
-               goto err;
-
-       return JS_TRUE;
-
-err:
-       if (HASHTABLE_VALID(&omap_table))
-               hashtable_destroy(&omap_table, FALSE);
-       if (POOL_VALID(&omap_pool))
-               (void) pool_destroy(&omap_pool);
-       if (POOL_VALID(&udata_pool))
-               (void) pool_destroy(&udata_pool);
-
-       return JS_FALSE;
-}
-
-void
-js_map_destroy(void)
-{
-
-       if (HASHTABLE_VALID(&omap_table))
-               hashtable_destroy(&omap_table, FALSE);
-       if (POOL_VALID(&omap_pool))
-               (void) pool_destroy(&omap_pool);
-       if (POOL_VALID(&udata_pool))
-               (void) pool_destroy(&udata_pool);
-}
-
-JSBool
-js_map_add(void *o, JSContext *cx, JSObject *obj, void *udata)
-{
-       omap_t  *omap;
-
-       assert(cx != NULL && obj != NULL && o != NULL);
-       if ((omap = (omap_t *)pool_alloc(&omap_pool, FALSE)) == NULL)
-               return FALSE;
-
-       omap->mem = o;
-       omap->cx = cx;
-       omap->obj = obj;
-       omap->udata = udata;
-
-       if (!hashtable_link(&omap_table, &omap->node, &omap->mem,
-           sizeof(void *), TRUE)) {
-               (void) pool_free((pnode_t *)omap);
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-omap_t *
-js_map_lookup(void *o)
-{
-
-       return (omap_t *)hashtable_lookup(&omap_table, &o, sizeof(void *));
-}
-
-void
-js_map_remove(omap_t *omap)
-{
-
-       hashtable_unlink(&omap_table, &omap->node);
-       (void) pool_free((pnode_t *)omap);
-}
-
-static int
-omap_keycmp(const void *a, const void *b, size_t s)
-{
-       long    da = (long)*(long *)a;
-       long    db = (long)*(long *)b;
-
-       return (int)(da - db);
-}
-
-static u_int32_t
-omap_keyhash(const void *a, size_t s)
-{
-       long    d = (long)*(long *)a;
-
-       return (u_int32_t)(d & 0xffffffff);
-}
diff --git a/mmsoftware/js/classes/js_gcroot.h b/mmsoftware/js/classes/js_gcroot.h
deleted file mode 100644 (file)
index c941601..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* $Id: js_gcroot.h,v 1.3 2006/10/18 05:07:42 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSGCROOT_H
-#define JSGCROOT_H
-
-
-
-#include <jsapi.h>
-
-#include <mmlist.h>
-#include <mmpool.h>
-#include <mmhash.h>
-
-
-
-#define UDATA_MAX      4
-
-/*
- * This structure allows to store/retreive user data from an object or
- * context, in a way that passing the udata_t * alone permits to retreive the
- * JSContext *, JSObject * and room for various user data pointers.
- * This is useful when implementing various classes.
- * We are using a pool_t in order to efficiently allocate and free these.
- */
-typedef struct udata {
-       pnode_t         node;
-       JSContext       *cx;
-       JSObject        *obj;
-       void            *udata[UDATA_MAX];
-} udata_t;
-
-/*
- * Used to implement a lookup hash table mapping arbitrary memory addresses to
- * their JSObject *.  This ideally would be on a per-context basis, but since
- * we must be able to only rely on the address, we must make this table
- * process-global.  In fact, we also need to obtain the JSContext pointer.
- * Thus, js_map_init() and js_map_destroy() should be called after runtime
- * creation and before runtime finalization, respectively.
- */
-typedef struct omap {
-       hashnode_t      node;
-       void            *mem;   /* Key */
-       JSContext       *cx;
-       JSObject        *obj;
-       void            *udata;
-} omap_t;
-
-
-
-extern JSBool  js_InitGCRoot(JSContext *);
-extern void    js_DestroyGCRoot(JSContext *);
-extern JSObject        *js_GCRoot(JSContext *);
-extern void    js_GCRoot_udata_set(JSContext *, udata_t *);
-extern udata_t *js_GCRoot_udata_get(JSContext *);
-
-extern udata_t *js_udata_alloc(JSContext *, JSObject *);
-extern void    js_udata_free(udata_t *);
-
-extern JSBool  js_map_init(void);
-extern void    js_map_destroy(void);
-extern JSBool  js_map_add(void *, JSContext *, JSObject *, void *);
-extern omap_t  *js_map_lookup(void *);
-extern void    js_map_remove(omap_t *);
-
-
-
-#endif
diff --git a/mmsoftware/js/classes/js_gd.c b/mmsoftware/js/classes/js_gd.c
deleted file mode 100644 (file)
index 7dcfcb0..0000000
+++ /dev/null
@@ -1,4357 +0,0 @@
-/* $Id: js_gd.c,v 1.6 2006/10/28 09:30:09 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Refer to http://www.boutell.com/gd/manual2.0.33.html for more information.
- *
- * XXX TODO XXX
- * - Implement GDIOCtx and related functions
- * - gdImageSetBrush() and gdImageSetTile() functions documentation specify
- *   that one should not use the special gdBrushed or gdTiled if no image was
- *   set for them or if their image were destroyed.  It would be lame to have
- *   to do this checking in this code, but we might have to.  Will have to try
- *   or to check the code to see if a crash can occur.
- */
-
-
-
-#include <sys/types.h>
-
-#include <stdint.h>
-
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-#include <gd.h>
-#include <gdfonts.h>
-#include <gdfontl.h>
-#include <gdfontmb.h>
-#include <gdfontg.h>
-#include <gdfontt.h>
-
-#include <js_gd.h>
-#include <js_file.h>
-
-
-
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-#define SP(n) \
-    { #n, n }
-
-
-
-/*
- * Static prototypes
- */
-
-/* GD */
-static JSBool  gd_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    gd_finalize(JSContext *, JSObject *);
-
-static JSBool  gd_sm_create(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  gd_sm_create_truecolor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSBool  gd_sm_create_from_file_i(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *, gdImagePtr (*)(FILE *), const char *);
-static JSBool  gd_sm_create_from_str_i(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *, gdImagePtr (*)(int, void *),
-                   const char *);
-
-static JSBool  gd_sm_create_from_jpeg(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gd_sm_create_from_jpeg_str(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gd_sm_create_from_png(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gd_sm_create_from_png_str(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gd_sm_create_from_gif(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gd_sm_create_from_gif_str(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gd_sm_create_from_gd(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gd_sm_create_from_gd_str(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gd_sm_create_from_gd2(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gd_sm_create_from_gd2_str(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gd_sm_create_from_gd2_part(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gd_sm_create_from_gd2_part_str(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gd_sm_create_from_wbmp(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gd_sm_create_from_wbmp_str(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gd_sm_create_from_xbm(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-#ifdef HAVE_XPM
-static JSBool  gd_sm_create_from_xpm(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-#endif
-static JSBool  gd_sm_true_color(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gd_sm_true_color_alpha(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gd_sm_ft_use_fontconfig(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-
-/* GDImage */
-static JSObject *js_InitGDImageClass(JSContext *, JSObject *);
-static JSBool  gdimage_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    gdimage_finalize(JSContext *, JSObject *);
-
-static JSBool  gdimage_get_property(JSContext *, JSObject *, jsval id,
-                   jsval *);
-static JSBool  gdimage_set_property(JSContext *, JSObject *, jsval id,
-                   jsval *);
-
-static JSBool  gdimage_m_image_destroy(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_save_file_i0(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, void (*)(gdImagePtr, FILE *));
-static JSBool  gdimage_m_save_file_i1(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, void (*)(gdImagePtr, FILE *, int));
-static JSBool  gdimage_m_save_str_i0(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, void *(*)(gdImagePtr, int *), const char *);
-static JSBool  gdimage_m_save_str_i1(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, void *(*)(gdImagePtr, int *, int), const char *);
-static JSBool  gdimage_m_jpeg(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_jpeg_str(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_gif(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_gif_str(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_gif_anim_begin(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_gif_anim_begin_str(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_gif_anim_add(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_gif_anim_add_str(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_gif_anim_end(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_gif_anim_end_str(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_png(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_png_str(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_png_ex(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_png_ex_str(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_wbmp(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_wbmp_str(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_gd(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  gdimage_m_gd_str(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_gd2(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_gd2_str(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_truecolor_to_palette(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_create_palette_from_truecolor(JSContext *,
-                   JSObject *, uintN, jsval *, jsval *);
-
-static JSBool  gdimage_m_set_pixel(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_primitive5_i(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, void (*)(gdImagePtr, int, int, int, int, int));
-static JSBool  gdimage_m_line(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_dashed_line(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static gdPointPtr      array_to_gdpoints_i(JSContext *, jsval, int *);
-static int     *array_to_ints_i(JSContext *, jsval, int *);
-static JSBool  gdimage_m_polygon_i(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, void (*)(gdImagePtr, gdPointPtr, int, int));
-static JSBool  gdimage_m_polygon(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_open_polygon(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_rectangle(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_filled_polygon(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_filled_rectangle(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_arc(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_filled_arc(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_filled_ellipse(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_fill_to_border(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_fill(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_set_antialiased(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_set_antialiaseddontblend(JSContext *, JSObject *,
-                   uintN, jsval *, jsval *);
-static JSBool  gdimage_m_set_brush(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_set_tile(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_set_style(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_set_thickness(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_alpha_blending(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_save_alpha(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_set_clip(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_get_clip(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_alpha(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_get_pixel(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_bounds_safe(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_image_sx(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_image_sy(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSBool  gdimage_m_int_int3_i(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, int (*)(gdImagePtr, int, int, int));
-static JSBool  gdimage_m_int_int4_i(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, int (*)(gdImagePtr, int, int, int, int));
-static JSBool  gdimage_m_color_allocate(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_color_allocate_alpha(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_color_closest(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_color_closest_alpha(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_color_closest_hwb(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_color_exact(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_color_resolve(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_color_resolve_alpha(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_colors_total(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_red(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_green(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_blue(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_get_interlaced(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_get_transparent(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_color_deallocate(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_color_transparent(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-
-static JSBool  gdimage_m_char_i(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *,
-                   void (*)(gdImagePtr, gdFontPtr, int, int, int, int));
-static JSBool  gdimage_m_string_i(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, void (*)(gdImagePtr, gdFontPtr, int, int,
-                   unsigned char *, int));
-static JSBool  gdimage_m_char(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_char_up(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_string(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_string_up(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_string_ft(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_string_ft_ex(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_string_ft_circle(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-
-static JSBool  gdimage_m_copy(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_copy_resized(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_copy_resampled(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_copy_rotated(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_copy_merge(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_copy_merge_gray(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  gdimage_m_palette_copy(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_square_to_circle(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-
-static JSBool  gdimage_m_compare(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  gdimage_m_interlace(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-/* GDFont */
-static JSObject        *js_InitGDFontClass(JSContext *, JSObject *, JSObject *);
-static JSBool  gdfont_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    gdfont_finalize(JSContext *, JSObject *);
-static JSObject        *gdfont_new(JSContext *, gdFontPtr);
-static gdFontPtr       gdfont_get(JSContext *, jsval);
-
-
-
-/*
- * Static globals
- */
-
-/*
- * GD
- */
-
-static JSClass gd_class = {
-       "GD", 0, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,
-       JS_ConvertStub, gd_finalize
-};
-
-/* Static methods */
-static JSFunctionSpec gd_smethods[] = {
-       { "create", gd_sm_create, 2, 0, 0 },
-       { "createTrueColor", gd_sm_create_truecolor, 2, 0, 0 },
-       { "createFromJpeg", gd_sm_create_from_jpeg, 1, 0, 0 },
-       { "createFromJpegStr", gd_sm_create_from_jpeg_str, 1, 0, 0 },
-       { "createFromPng", gd_sm_create_from_png, 1, 0, 0 },
-       { "createFromPngStr", gd_sm_create_from_png_str, 1, 0, 0 },
-       { "createFromGif", gd_sm_create_from_gif, 1, 0, 0 },
-       { "createFromGifStr", gd_sm_create_from_gif_str, 1, 0, 0 },
-       { "createFromGd", gd_sm_create_from_gd, 1, 0, 0 },
-       { "createFromGdStr", gd_sm_create_from_gd_str, 1, 0, 0 },
-       { "createFromGd2", gd_sm_create_from_gd2, 1, 0, 0 },
-       { "createFromGd2Str", gd_sm_create_from_gd2_str, 1, 0, 0 },
-       { "createFromGd2Part", gd_sm_create_from_gd2_part, 5, 0, 0 },
-       { "createFromGd2PartStr", gd_sm_create_from_gd2_part_str, 5, 0, 0 },
-       { "createFromWBMP", gd_sm_create_from_wbmp, 1, 0, 0 },
-       { "createFromWBMPStr", gd_sm_create_from_wbmp_str, 1, 0, 0 },
-       { "createFromXbm", gd_sm_create_from_xbm, 1, 0, 0 },
-#ifdef HAVE_XPM
-       { "createFromXpm", gd_sm_create_from_xpm, 1, 0, 0 },
-#endif
-       { "trueColor", gd_sm_true_color, 3, 0, 0 },
-       { "trueColorAlpha", gd_sm_true_color_alpha, 4, 0, 0 },
-       { "ftUseFontConfig", gd_sm_ft_use_fontconfig, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/* Static properties */
-static struct property_spec    gd_sprops[] = {
-       SP(gdDisposalNone),
-       SP(gdDisposalUnknown),
-       SP(gdDisposalRestoreBackground),
-       SP(gdDisposalRestorePrevious),
-       SP(GD2_FMT_RAW),
-       SP(GD2_FMT_COMPRESSED),
-       SP(gdAntiAliased),
-       SP(gdBrushed),
-       SP(gdMaxColors),
-       SP(gdStyled),
-       SP(gdStyledBrushed),
-       SP(gdDashSize),
-       SP(gdTiled),
-       SP(gdTransparent),
-       SP(gdArc),
-       SP(gdChord),
-       SP(gdPie),
-       SP(gdNoFill),
-       SP(gdEdged),
-       SP(gdAlphaOpaque),
-       SP(gdAlphaTransparent),
-       SP(GD_CMP_IMAGE),
-       SP(GD_CMP_NUM_COLORS),
-       SP(GD_CMP_COLOR),
-       SP(GD_CMP_SIZE_X),
-       SP(GD_CMP_SIZE_Y),
-       SP(GD_CMP_TRANSPARENT),
-       SP(GD_CMP_BACKGROUND),
-       SP(GD_CMP_INTERLACE),
-       SP(GD_CMP_TRUECOLOR),
-       SP(gdFTEX_Unicode),
-       SP(gdFTEX_Shift_JIS),
-       SP(gdFTEX_Big5),
-       { NULL, 0 }
-};
-
-
-
-/*
- * GDImage
- */
-
-/* Class */
-static JSClass gdimage_class = {
-       "GDImage", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       gdimage_get_property, gdimage_set_property, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, gdimage_finalize
-};
-
-/* Properties */
-enum gdimage_props {
-       GDIMAGE_P_SX,
-       GDIMAGE_P_SY,
-       GDIMAGE_P_MAX
-};
-
-static JSPropertySpec gdimage_properties[GDIMAGE_P_MAX + 1] = {
-       { "sx", GDIMAGE_P_SX, JSPROP_ENUMERATE | JSPROP_READONLY, NULL, NULL },
-       { "sy", GDIMAGE_P_SY, JSPROP_ENUMERATE | JSPROP_READONLY, NULL, NULL },
-       { NULL, 0, 0, NULL, NULL }
-};
-
-/* Methods */
-static JSFunctionSpec gdimage_methods[] = {
-       { "destroy", gdimage_m_image_destroy, 0, 0, 0 },
-       { "jpeg", gdimage_m_jpeg, 2, 0, 0 },
-       { "jpegStr", gdimage_m_jpeg_str, 1, 0, 0 },
-       { "gif", gdimage_m_gif, 1, 0, 0 },
-       { "gifStr", gdimage_m_gif_str, 0, 0, 0 },
-       { "gifAnimBegin", gdimage_m_gif_anim_begin, 3, 0, 0 },
-       { "gifAnimBeginStr", gdimage_m_gif_anim_begin_str, 2, 0, 0 },
-       { "gifAnimAdd", gdimage_m_gif_anim_add, 7, 0, 0 },
-       { "gifAnimAddStr", gdimage_m_gif_anim_add_str, 6, 0, 0 },
-       { "gifAnimEnd", gdimage_m_gif_anim_end, 1, 0, 0 },
-       { "gifAnimEndStr", gdimage_m_gif_anim_end_str, 0, 0, 0 },
-       { "png", gdimage_m_png, 1, 0, 0 },
-       { "pngStr", gdimage_m_png_str, 0, 0, 0 },
-       { "pngEx", gdimage_m_png_ex, 2, 0, 0 },
-       { "pngExStr", gdimage_m_png_ex_str, 1, 0, 0 },
-       { "wbmp", gdimage_m_wbmp, 2, 0, 0 },
-       { "wbmpStr", gdimage_m_wbmp_str, 1, 0, 0 },
-       { "gd", gdimage_m_gd, 1, 0, 0 },
-       { "gdStr", gdimage_m_gd_str, 0, 0, 0 },
-       { "gd2", gdimage_m_gd2, 3, 0, 0 },
-       { "gd2Str", gdimage_m_gd2_str, 2, 0, 0 },
-       { "trueColorToPalette", gdimage_m_truecolor_to_palette, 2, 0, 0 },
-       { "createPaletteFromTrueColor",
-           gdimage_m_create_palette_from_truecolor, 2, 0, 0 },
-
-       { "setPixel", gdimage_m_set_pixel, 3, 0, 0 },
-       { "line", gdimage_m_line, 5, 0, 0 },
-       { "dashedLine", gdimage_m_dashed_line, 5, 0, 0 },
-       { "polygon", gdimage_m_polygon, 2, 0, 0 },
-       { "openPolygon", gdimage_m_open_polygon, 2, 0, 0 },
-       { "rectangle", gdimage_m_rectangle, 5, 0, 0 },
-       { "filledPolygon", gdimage_m_filled_polygon, 2, 0, 0 },
-       { "filledRectangle", gdimage_m_filled_rectangle, 5, 0, 0 },
-       { "arc", gdimage_m_arc, 7, 0, 0 },
-       { "filledArc", gdimage_m_filled_arc, 8, 0, 0 },
-       { "filledEllipse", gdimage_m_filled_ellipse, 5, 0, 0 },
-       { "fillToBorder", gdimage_m_fill_to_border, 4, 0, 0 },
-       { "fill", gdimage_m_fill, 3, 0, 0 },
-       { "setAntiAliased", gdimage_m_set_antialiased, 1, 0, 0 },
-       { "setAntiAliasedDontBlend", gdimage_m_set_antialiaseddontblend,
-           2, 0, 0 },
-       { "setBrush", gdimage_m_set_brush, 1, 0, 0 },
-       { "setTile", gdimage_m_set_tile, 1, 0, 0 },
-       { "setStyle", gdimage_m_set_style, 1, 0, 0 },
-       { "setThickness", gdimage_m_set_thickness, 1, 0, 0 },
-       { "alphaBlending", gdimage_m_alpha_blending, 1, 0, 0 },
-       { "saveAlpha", gdimage_m_save_alpha, 1, 0, 0 },
-       { "setClip", gdimage_m_set_clip, 4, 0, 0 },
-       { "getClip", gdimage_m_get_clip, 0, 0, 0 },
-       { "alpha", gdimage_m_alpha, 1, 0, 0 },
-       { "getPixel", gdimage_m_get_pixel, 2, 0, 0 },
-       { "boundsSafe", gdimage_m_bounds_safe, 2, 0, 0 },
-       { "imageSX", gdimage_m_image_sx, 0, 0, 0 },
-       { "imageSY", gdimage_m_image_sy, 0, 0, 0 },
-
-       { "colorAllocate", gdimage_m_color_allocate, 3, 0, 0 },
-       { "colorAllocateAlpha", gdimage_m_color_allocate_alpha, 4, 0, 0 },
-       { "colorClosest", gdimage_m_color_closest, 3, 0, 0 },
-       { "colorClosestAlpha", gdimage_m_color_closest_alpha, 4, 0, 0 },
-       { "colorClosestHWB", gdimage_m_color_closest_hwb, 3, 0, 0 },
-       { "colorExact", gdimage_m_color_exact, 3, 0, 0 },
-       { "colorResolve", gdimage_m_color_resolve, 3, 0, 0 },
-       { "colorResolveAlpha", gdimage_m_color_resolve_alpha, 4, 0, 0 },
-       { "colorsTotal", gdimage_m_colors_total, 0, 0, 0 },
-       { "red", gdimage_m_red, 1, 0, 0 },
-       { "green", gdimage_m_green, 1, 0, 0 },
-       { "blue", gdimage_m_blue, 1, 0, 0 },
-       { "getInterlaced", gdimage_m_get_interlaced, 0, 0, 0 },
-       { "getTransparent", gdimage_m_get_transparent, 0, 0, 0 },
-       { "colorDeallocate", gdimage_m_color_deallocate, 1, 0, 0 },
-       { "colorTransparent", gdimage_m_color_transparent, 1, 0, 0 },
-
-       /*
-        * We don't implement charRight16, charUp16, stringRight16 and
-        * stringUp16 because GD fonts actually don't support 16-bit chars.
-        * stringFt[Ex] may be used instead which allow UTF-8 and use of
-        * external fonts.  Moreover, we don't support stringFtt which was for
-        * use with FontType v1, and is now deprecated (calling the v2
-        * function internally for compatibility).
-        */
-       { "charRight", gdimage_m_char, 5, 0, 0 },       /* char == reserved! */
-       { "charUp", gdimage_m_char_up, 5, 0, 0 },
-       { "stringRight", gdimage_m_string, 5, 0, 0 },   /* string reserved! */
-       { "stringUp", gdimage_m_string_up, 5, 0, 0 },
-       { "stringFt", gdimage_m_string_ft, 7, 0, 0 },
-       { "stringFtEx", gdimage_m_string_ft_ex, 8, 0, 0 },
-       { "stringFtCircle", gdimage_m_string_ft_circle, 10, 0, 0 },
-
-       { "copy", gdimage_m_copy, 7, 0, 0 },
-       { "copyResized", gdimage_m_copy_resized, 9, 0, 0 },
-       { "copyResampled", gdimage_m_copy_resampled, 9, 0, 0 },
-       { "copyRotated", gdimage_m_copy_rotated, 8, 0, 0 },
-       { "copyMerge", gdimage_m_copy_merge, 8, 0, 0 },
-       { "copyMergeGray", gdimage_m_copy_merge_gray, 8, 0, 0 },
-       { "paletteCopy", gdimage_m_palette_copy, 1, 0, 0 },
-       { "squareToCircle", gdimage_m_square_to_circle, 1, 0, 0 },
-
-       { "compare", gdimage_m_compare, 1, 0, 0 },
-       { "interlace", gdimage_m_interlace, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-
-
-/*
- * GDFont
- */
-
-/* Class */
-static JSClass gdfont_class = {
-       "GDFont", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,
-       JS_ConvertStub, gdfont_finalize
-};
-
-
-
-/*
- * GD object control
- */
-
-JSObject *
-js_InitGDClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &gd_class, gd_constructor,
-           0, NULL, NULL, NULL, gd_smethods)) == NULL) {
-               (void) fprintf(stderr, "Error initializing GD class\n");
-               goto err;
-       }
-
-       /* Create static properties. */
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "GD: JS_GetConstructor == NULL\n");
-               return NULL;
-       }
-       for (sp = gd_sprops; sp->name != NULL; sp++) {
-               if (JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT) == JS_FALSE) {
-                       (void) fprintf(stderr,
-                           "GD: Error defining property %s\n", sp->name);
-                       return NULL;
-               }
-       }
-
-       /*
-        * Initialize GDImage class since we'll need to instanciate it from C
-        */
-       if (js_InitGDImageClass(cx, obj) == NULL) {
-               (void) fprintf(stderr, "GD: InitGDImageClass()\n");
-               goto err;
-       }
-       /*
-        * Same for GDFont, which will use our supplied GD object pointer to
-        * set properties for existing fonts.
-        */
-       if (js_InitGDFontClass(cx, obj, ctor) == NULL) {
-               (void) fprintf(stderr, "GD: InitGDFontClass()\n");
-               goto err;
-       }
-
-       if (gdFontCacheSetup() != 0) {
-               (void) fprintf(stderr, "gdFontCacheSetup()\n");
-               goto err;
-       }
-
-       return proto;
-
-err:
-       return NULL;
-}
-
-/* ARGSUSED */
-static JSBool
-gd_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-       QUEUE_EXCEPTION("GD object not user-instanciable");
-
-       return JS_FALSE;
-}
-
-/* ARGSUSED */
-static void
-gd_finalize(JSContext *cx, JSObject *obj)
-{
-
-       /* NOOP */
-}
-
-
-
-/* GD static methods */
-static JSBool
-gd_sm_create(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img = NULL;
-       JSObject        *o;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-
-       if ((img = gdImageCreate(JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1]))) == NULL) {
-               QUEUE_EXCEPTION("gdImageCreate()");
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &gdimage_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-       if (!JS_SetPrivate(cx, o, img)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (img)
-               gdImageDestroy(img);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gd_sm_create_truecolor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img = NULL;
-       JSObject        *o;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-
-       if ((img = gdImageCreateTrueColor(JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1]))) == NULL) {
-               QUEUE_EXCEPTION("gdImageCreate()");
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &gdimage_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-       if (!JS_SetPrivate(cx, o, img)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (img != NULL)
-               gdImageDestroy(img);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gd_sm_create_from_file_i(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, gdImagePtr (*funcptr)(FILE *), const char *funcname)
-{
-       FILE            *fh;
-       gdImagePtr      img = NULL;
-       JSObject        *o;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if ((fh = file_fh(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a File object");
-               goto err;
-       }
-
-       if ((img = funcptr(fh)) == NULL) {
-               QUEUE_EXCEPTION(funcname);
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &gdimage_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-       if (!JS_SetPrivate(cx, o, img)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (img != NULL)
-               gdImageDestroy(img);
-
-       return JS_FALSE;
-}
-
-/*
- * We replace gdImageCreateFrom*Ptr() by methods using a String.
- */
-static JSBool
-gd_sm_create_from_str_i(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval, gdImagePtr (*funcptr)(int, void *),
-    const char *funcname)
-{
-       JSString        *str;
-       char            *bytes;
-       size_t          size;
-       gdImagePtr      img = NULL;
-       JSObject        *o;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-
-       str = JSVAL_TO_STRING(argv[0]);
-       if ((bytes = JS_GetStringBytes(str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       size = JS_GetStringLength(str);
-
-       if ((img = funcptr((int)size, bytes)) == NULL) {
-               QUEUE_EXCEPTION(funcname);
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &gdimage_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-       if (!JS_SetPrivate(cx, o, img)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (img != NULL)
-               gdImageDestroy(img);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gd_sm_create_from_jpeg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gd_sm_create_from_file_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromJpeg, "gdImageCreateFromJpeg()");
-}
-
-static JSBool
-gd_sm_create_from_jpeg_str(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return gd_sm_create_from_str_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromJpegPtr, "gdImageCreateFromJpegPtr()");
-}
-
-static JSBool
-gd_sm_create_from_png(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gd_sm_create_from_file_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromPng, "gdImageCreateFromPng()");
-}
-
-static JSBool
-gd_sm_create_from_png_str(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return gd_sm_create_from_str_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromPngPtr, "gdImageCreateFromPngPtr()");
-}
-
-static JSBool
-gd_sm_create_from_gif(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gd_sm_create_from_file_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromGif, "gdImageCreateFromGif()");
-}
-
-static JSBool
-gd_sm_create_from_gif_str(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return gd_sm_create_from_str_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromGifPtr, "gdImageCreateFromGifPtr()");
-}
-
-static JSBool
-gd_sm_create_from_gd(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gd_sm_create_from_file_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromGd, "gdImageCreateFromGd()");
-}
-
-static JSBool
-gd_sm_create_from_gd_str(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return gd_sm_create_from_str_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromGdPtr, "gdImageCreateFromGdPtr()");
-}
-
-static JSBool
-gd_sm_create_from_gd2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gd_sm_create_from_file_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromGd2, "gdImageCreateFromGd2()");
-}
-
-static JSBool
-gd_sm_create_from_gd2_str(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return gd_sm_create_from_str_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromGd2Ptr, "gdImageCreateFromGd2Ptr()");
-}
-
-static JSBool
-gd_sm_create_from_gd2_part(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       FILE            *fh;
-       gdImagePtr      img = NULL;
-       JSObject        *o;
-
-       if (argc != 5) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if ((fh = file_fh(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a File object");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[3])) {
-               QUEUE_EXCEPTION("Argument 4 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[4])) {
-               QUEUE_EXCEPTION("Argument 5 not an Integer");
-               goto err;
-       }
-
-       if ((img = gdImageCreateFromGd2Part(fh, JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]),
-           JSVAL_TO_INT(argv[4]))) == NULL) {
-               QUEUE_EXCEPTION("gdImageCreateFromGd2Part()");
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &gdimage_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-       if (!JS_SetPrivate(cx, o, img)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (img != NULL)
-               gdImageDestroy(img);
-
-       return JS_FALSE;
-}
-
-/*
- * We replace gdImageCreateFrom*Ptr() by methods using a String.
- */
-static JSBool
-gd_sm_create_from_gd2_part_str(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       JSString        *str;
-       char            *bytes;
-       size_t          size;
-       gdImagePtr      img = NULL;
-       JSObject        *o;
-
-       if (argc != 5) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[3])) {
-               QUEUE_EXCEPTION("Argument 4 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[4])) {
-               QUEUE_EXCEPTION("Argument 5 not an Integer");
-               goto err;
-       }
-
-       str = JSVAL_TO_STRING(argv[0]);
-       if ((bytes = JS_GetStringBytes(str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       size = JS_GetStringLength(str);
-
-       if ((img = gdImageCreateFromGd2PartPtr((int)size, bytes,
-           JSVAL_TO_INT(argv[1]), JSVAL_TO_INT(argv[2]),
-           JSVAL_TO_INT(argv[3]), JSVAL_TO_INT(argv[4]))) == NULL) {
-               QUEUE_EXCEPTION("GdImageCreateFromGd2PartPtr()");
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &gdimage_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-       if (!JS_SetPrivate(cx, o, img)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (img != NULL)
-               gdImageDestroy(img);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gd_sm_create_from_wbmp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gd_sm_create_from_file_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromWBMP, "gdImageCreateFromWBMP()");
-}
-
-static JSBool
-gd_sm_create_from_wbmp_str(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return gd_sm_create_from_str_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromWBMPPtr, "gdImageCreateFromWBMPPtr()");
-}
-
-static JSBool
-gd_sm_create_from_xbm(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gd_sm_create_from_file_i(cx, obj, argc, argv, rval,
-               gdImageCreateFromXbm, "gdImageCreateFromXbm()");
-}
-
-#ifdef HAVE_XPM
-static JSBool
-gd_sm_create_from_xpm(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, gdImagePtr (*funcptr)(FILE *), const char *funcname)
-{
-       const char      *bytes;
-       gdImagePtr      img = NULL;
-       JSObject        *o;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0]) ||
-           (bytes = JS_GetStringBytes(argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-
-       /* XXX Perform path sanity/access checking */
-       if ((img = gdImageCreateFromXpm(bytes)) == NULL) {
-               QUEUE_EXCEPTION("gdImageCreateFromXpm()");
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &gdimage_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-       if (!JS_SetPrivate(cx, o, img)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (img != NULL)
-               gdImageDestroy(img);
-
-       return JS_FALSE;
-}
-#endif
-
-static JSBool
-gd_sm_true_color(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       int     col, i1, i2, i3;
-
-       if (argc != 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               goto err;
-       }
-
-       /* Since gdTrueColor is a macro, avoid side-effects */
-       i1 = JSVAL_TO_INT(argv[0]);
-       i2 = JSVAL_TO_INT(argv[1]);
-       i3 = JSVAL_TO_INT(argv[2]);
-       col = gdTrueColor(i1, i2, i3);
-       *rval = INT_TO_JSVAL(col);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gd_sm_true_color_alpha(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       int     col, i1, i2, i3, i4;
-
-       if (argc != 4) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[3])) {
-               QUEUE_EXCEPTION("Argument 4 not an Integer");
-               goto err;
-       }
-
-       /* Since gdTrueColorAlpha() is a macro, avoid side-effects */
-       i1 = JSVAL_TO_INT(argv[0]);
-       i2 = JSVAL_TO_INT(argv[1]);
-       i3 = JSVAL_TO_INT(argv[2]);
-       i4 = JSVAL_TO_INT(argv[3]);
-       col = gdTrueColorAlpha(i1, i2, i3, i4);
-       *rval = INT_TO_JSVAL(col);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gd_sm_ft_use_fontconfig(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       int     v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_BOOLEAN(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a Boolean");
-               goto err;
-       }
-
-       v = gdFTUseFontConfig((int)JSVAL_TO_BOOLEAN(argv[0]));
-       *rval = BOOLEAN_TO_JSVAL((JSBool)v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-
-/*
- * GDImage object control
- */
-
-static JSObject *
-js_InitGDImageClass(JSContext *cx, JSObject *obj)
-{
-
-       return (JS_InitClass(cx, obj, NULL, &gdimage_class,
-           gdimage_constructor, 0, gdimage_properties, gdimage_methods, NULL,
-           NULL));
-}
-
-/* ARGSUSED */
-static JSBool
-gdimage_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("GDImage class not user-instanciable");
-
-       return JS_FALSE;
-}
-
-static void
-gdimage_finalize(JSContext *cx, JSObject *obj)
-{
-       gdImagePtr      img;
-
-       if ((img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL))
-           != NULL) {
-               gdImageDestroy(img);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-}
-
-
-/* GDImage object property setters/getters */
-static JSBool
-gdimage_get_property(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-       jsint           p;
-       gdImagePtr      img;
-
-       if (!JSVAL_IS_INT(id))
-               return JS_TRUE;
-       p = (int)JSVAL_TO_INT(id);
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       switch (p) {
-       case GDIMAGE_P_SX:
-               *vp = INT_TO_JSVAL(img->sx);
-               break;
-       case GDIMAGE_P_SY:
-               *vp = INT_TO_JSVAL(img->sy);
-               break;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_set_property(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-       jsint           p;
-       gdImagePtr      img;
-
-       if (!JSVAL_IS_INT(id))
-               return JS_TRUE;
-       p = (int)JSVAL_TO_INT(id);
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       switch (p) {
-               /* XXX No writable property yet */
-       }
-
-       return JS_TRUE;
-}
-
-
-/*
- * GDImage object properties
- */
-
-/*
- * GDImage object methods
- */
-
-static JSBool
-gdimage_m_image_destroy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageDestroy(img);
-       (void) JS_SetPrivate(cx, obj, NULL);
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_TRUE;
-}
-
-/*
- * Called by multiple similar functions
- */
-static JSBool
-gdimage_m_save_file_i0(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, void (*funcptr)(gdImagePtr, FILE *))
-{
-       FILE            *fh;
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if ((fh = file_fh(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a File object");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       funcptr(img, fh);
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_save_file_i1(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, void (*funcptr)(gdImagePtr, FILE *, int))
-{
-       FILE            *fh;
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if ((fh = file_fh(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a File object");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       funcptr(img, fh, JSVAL_TO_INT(argv[1]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_save_str_i0(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, void *(*funcptr)(gdImagePtr, int *), const char *funcname)
-{
-       gdImagePtr      img;
-       void            *data = NULL;
-       int             size;
-       JSString        *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       if ((data = funcptr(img, &size)) == NULL) {
-               QUEUE_EXCEPTION(funcname);
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, data, size)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-       gdFree(data);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (data != NULL)
-               gdFree(data);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_save_str_i1(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, void *(*funcptr)(gdImagePtr, int *, int),
-    const char *funcname)
-{
-       gdImagePtr      img;
-       void            *data = NULL;
-       int             size;
-       JSString        *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       if ((data = funcptr(img, &size, JSVAL_TO_INT(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION(funcname);
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, data, size)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-       gdFree(data);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (data != NULL)
-               gdFree(data);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_jpeg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_save_file_i1(cx, obj, argc, argv, rval, gdImageJpeg);
-}
-
-static JSBool
-gdimage_m_jpeg_str(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_save_str_i1(cx, obj, argc, argv, rval,
-           gdImageJpegPtr, "gdImageJpegPtr()");
-}
-
-static JSBool
-gdimage_m_gif(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_save_file_i0(cx, obj, argc, argv, rval, gdImageGif);
-}
-
-static JSBool
-gdimage_m_gif_str(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_save_str_i0(cx, obj, argc, argv, rval,
-           gdImageGifPtr, "gdImageGifPtr()");
-}
-
-static JSBool
-gdimage_m_gif_anim_begin(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       FILE            *fh;
-       gdImagePtr      img;
-
-       if (argc != 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if ((fh = file_fh(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a File object");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageGifAnimBegin(img, fh, JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_gif_anim_begin_str(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-       void            *data = NULL;
-       int             size;
-       JSString        *str;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       if ((data = gdImageGifAnimBeginPtr(img, &size, JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1]))) == NULL) {
-               QUEUE_EXCEPTION("gdImageGifAnimBeginPtr()");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, data, size)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-       gdFree(data);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (data != NULL)
-               gdFree(data);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_gif_anim_add(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       FILE            *fh;
-       gdImagePtr      img, img2;
-
-       if (argc != 7) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if ((fh = file_fh(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a File object");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[3])) {
-               QUEUE_EXCEPTION("Argument 4 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[4])) {
-               QUEUE_EXCEPTION("Argument 5 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[5])) {
-               QUEUE_EXCEPTION("Argument 6 not an Integer");
-               goto err;
-       }
-       if (JSVAL_IS_NULL(argv[6]))
-               img2 = NULL;
-       else {
-               JSObject        *o;
-
-               if (!JSVAL_IS_OBJECT(argv[6])) {
-                       QUEUE_EXCEPTION(
-                           "Argument 7 not Null or GDImage object");
-                       goto err;
-               }
-               o = JSVAL_TO_OBJECT(argv[6]);
-               if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-                       QUEUE_EXCEPTION(
-                           "Argument 7 not Null or GDImage object");
-                       goto err;
-               }
-
-               img2 = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-               assert(img2 != NULL);
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageGifAnimAdd(img, fh, JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]),
-           JSVAL_TO_INT(argv[4]), JSVAL_TO_INT(argv[5]), img2);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_gif_anim_add_str(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img, img2;
-       void            *data = NULL;
-       int             size;
-       JSString        *str;
-
-       if (argc != 6) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[3])) {
-               QUEUE_EXCEPTION("Argument 4 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[4])) {
-               QUEUE_EXCEPTION("Argument 5 not an Integer");
-               goto err;
-       }
-       if (JSVAL_IS_NULL(argv[5]))
-               img2 = NULL;
-       else {
-               JSObject        *o;
-
-               if (!JSVAL_IS_OBJECT(argv[5])) {
-                       QUEUE_EXCEPTION(
-                           "Argument 6 not Null or GDImage object");
-                       goto err;
-               }
-               o = JSVAL_TO_OBJECT(argv[6]);
-               if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-                       QUEUE_EXCEPTION(
-                           "Argument 6 not Null or GDImage object");
-                       goto err;
-               }
-
-               img2 = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-               assert(img2 != NULL);
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       if ((data = gdImageGifAnimAddPtr(img, &size, JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1]), JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]),
-           JSVAL_TO_INT(argv[4]), img2)) == NULL) {
-               QUEUE_EXCEPTION("gdImageGifAnimAddPtr()");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, data, size)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-       gdFree(data);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (data != NULL)
-               gdFree(data);
-
-       return JS_FALSE;
-}
-
-/*
- * For consistency, GD authors should have made these two still require the
- * gdImagePtr argument.  However, they don't... so we had to rewrite these.
- * We however still present a consistent API and attach this method to the
- * GDImage object.
- */
-static JSBool
-gdimage_m_gif_anim_end(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       FILE    *fh;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if ((fh = file_fh(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a File object");
-               return JS_FALSE;
-       }
-
-       gdImageGifAnimEnd(fh);
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_gif_anim_end_str(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       void            *data = NULL;
-       int             size;
-       JSString        *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       if ((data = gdImageGifAnimEndPtr(&size)) == NULL) {
-               QUEUE_EXCEPTION("gdImageGifAnimEndPtr()");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, data, size)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-       gdFree(data);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (data != NULL)
-               gdFree(data);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_png(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_save_file_i0(cx, obj, argc, argv, rval, gdImagePng);
-}
-
-static JSBool
-gdimage_m_png_str(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_save_str_i0(cx, obj, argc, argv, rval, gdImagePngPtr,
-           "gdImagePngPtr()");
-}
-
-static JSBool
-gdimage_m_png_ex(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_save_file_i1(cx, obj, argc, argv, rval, gdImagePngEx);
-}
-
-static JSBool
-gdimage_m_png_ex_str(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_save_str_i1(cx, obj, argc, argv, rval,
-           gdImagePngPtrEx, "gdImagePngPtrEx()");
-}
-
-/*
- * GD is inconsistent and gdImageWBMP() takes int argument before the FILE *.
- * We however make it consistent in this API.
- */
-static JSBool
-gdimage_m_wbmp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       FILE            *fh;
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if ((fh = file_fh(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a File object");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageWBMP(img, JSVAL_TO_INT(argv[1]), fh);
-
-       return JS_TRUE;
-}
-
-/*
- * GD documentation states that gdImageWBMPPtr() does't take an int, but it
- * does after the FILE *, like gdImageWBMP() but with revesed arguments order.
- * This function seemed consistent, at least.
- */
-static JSBool
-gdimage_m_wbmp_str(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_save_str_i1(cx, obj, argc, argv, rval, gdImageWBMPPtr,
-           "gdImageWBMPPtr()");
-}
-
-static JSBool
-gdimage_m_gd(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_save_file_i0(cx, obj, argc, argv, rval, gdImageGd);
-}
-
-static JSBool
-gdimage_m_gd_str(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_save_str_i0(cx, obj, argc, argv, rval, gdImageGdPtr,
-           "gdImageGdPtr()");
-}
-
-static JSBool
-gdimage_m_gd2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       FILE            *fh;
-       gdImagePtr      img;
-
-       if (argc != 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if ((fh = file_fh(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a File object");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageGd2(img, fh, JSVAL_TO_INT(argv[1]), JSVAL_TO_INT(argv[2]));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_gd2_str(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       void            *data = NULL;
-       int             size;
-       JSString        *str;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       /*
-        * Also an inconsistent GD function as it requires the int pointer
-        * after the other integer arguments.
-        */
-       if ((data = gdImageGd2Ptr(img, JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1]), &size)) == NULL) {
-               QUEUE_EXCEPTION("gdImageGd2Ptr()");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, data, size)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-       gdFree(data);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (data != NULL)
-               gdFree(data);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_truecolor_to_palette(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageTrueColorToPalette(img, JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_create_palette_from_truecolor(JSContext *cx, JSObject *obj,
-    uintN argc, jsval *argv, jsval *rval)
-{
-       gdImagePtr      img, img2 = NULL;
-       JSObject        *o;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       if ((img2 = gdImageCreatePaletteFromTrueColor(img,
-           JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]))) == NULL) {
-               QUEUE_EXCEPTION("gdImageCreatePaletteFromTrueColor()");
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &gdimage_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-       if (!JS_SetPrivate(cx, o, img2)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (img2 != NULL)
-               gdFree(img2);
-
-       return JS_FALSE;
-}
-
-
-static JSBool
-gdimage_m_set_pixel(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageSetPixel(img, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_primitive5_i(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, void (*funcptr)(gdImagePtr, int, int, int, int, int))
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 5) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[3])) {
-               QUEUE_EXCEPTION("Argument 4 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[4])) {
-               QUEUE_EXCEPTION("Argument 5 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       funcptr(img, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]),
-           JSVAL_TO_INT(argv[4]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_line(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_primitive5_i(cx, obj, argc, argv, rval, gdImageLine);
-}
-
-static JSBool
-gdimage_m_dashed_line(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_primitive5_i(cx, obj, argc, argv, rval,
-           gdImageDashedLine);
-}
-
-/*
- * Converts a JS array of integer pairs to a C gdPoint array, which must be
- * freed by the caller on success.  On failure, we return NULL and
- * automatically send an appropriate exception.  On success, we return the
- * gdPoint array pointer and store the number of verticles stored in it via
- * the provided size pointer.
- */
-static gdPointPtr
-array_to_gdpoints_i(JSContext *cx, jsval a, int *size)
-{
-       JSObject        *o;
-       jsuint          len;
-       JSIdArray       *ida = NULL;
-       gdPointPtr      pts = NULL;
-       int             i, i2, i3;
-       jsval           id, val;
-
-       if (!JSVAL_IS_OBJECT(a) ||
-           !JS_IsArrayObject(cx, (o = JSVAL_TO_OBJECT(a)))) {
-               QUEUE_EXCEPTION("Argument not an Array object");
-               goto err;
-       }
-       if (!JS_GetArrayLength(cx, o, &len) || ((len & 1) != 0)) {
-               QUEUE_EXCEPTION("Array not holding even pairs");
-               goto err;
-       }
-
-       len /= 2;
-       if ((pts = malloc(sizeof(gdPoint) * len)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       if ((ida = JS_Enumerate(cx, o)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       for (i3 = i2 = i = 0; i < ida->length; i++) {
-               JS_IdToValue(cx, ida->vector[i], &id);
-               if (!JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) ||
-                   JSVAL_IS_VOID(val))
-                       continue;
-               if (!JSVAL_IS_INT(val)) {
-                       QUEUE_EXCEPTION("Array elements not all Integers");
-                       goto err;
-               }
-               if ((i2++ & 1) == 0)
-                       pts[i3].x = JSVAL_TO_INT(val);
-               else
-                       pts[i3++].y = JSVAL_TO_INT(val);
-       }
-       JS_DestroyIdArray(cx, ida);
-       ida = NULL;
-
-       *size = len;
-       return pts;
-
-err:
-       if (ida != NULL)
-               JS_DestroyIdArray(cx, ida);
-       if (pts != NULL)
-               free(pts);
-       *size = 0;
-
-       return NULL;
-}
-
-/*
- * Converts a JS array of integer pairs to a C int array, which must be
- * freed by the caller on success.  On failure, we return NULL and
- * automatically send an appropriate exception.  On success, we return the
- * int array pointer and store the number of entries stored in it via
- * the provided size pointer.
- */
-static int *
-array_to_ints_i(JSContext *cx, jsval a, int *size)
-{
-       JSObject        *o;
-       jsuint          len;
-       JSIdArray       *ida = NULL;
-       int             *pts = NULL;
-       int             i, i2;
-       jsval           id, val;
-
-       if (!JSVAL_IS_OBJECT(a) ||
-           !JS_IsArrayObject(cx, (o = JSVAL_TO_OBJECT(a)))) {
-               QUEUE_EXCEPTION("Argument not an Array object");
-               goto err;
-       }
-       if (!JS_GetArrayLength(cx, o, &len)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       if ((pts = malloc(sizeof(int) * len)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       if ((ida = JS_Enumerate(cx, o)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       for (i2 = i = 0; i < ida->length; i++) {
-               JS_IdToValue(cx, ida->vector[i], &id);
-               if (!JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) ||
-                   JSVAL_IS_VOID(val))
-                       continue;
-               if (!JSVAL_IS_INT(val)) {
-                       QUEUE_EXCEPTION("Array elements not all Integers");
-                       goto err;
-               }
-               pts[i2++] = JSVAL_TO_INT(val);
-       }
-       JS_DestroyIdArray(cx, ida);
-       ida = NULL;
-
-       *size = len;
-       return pts;
-
-err:
-       if (ida != NULL)
-               JS_DestroyIdArray(cx, ida);
-       if (pts != NULL)
-               free(pts);
-       *size = 0;
-
-       return NULL;
-}
-
-static JSBool
-gdimage_m_polygon_i(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, void (*funcptr)(gdImagePtr, gdPointPtr, int, int))
-{
-       gdImagePtr      img;
-       gdPointPtr      pts = NULL;
-       int             size;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if ((pts = array_to_gdpoints_i(cx, argv[0], &size)) == NULL)
-               goto err;
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       funcptr(img, pts, size, JSVAL_TO_INT(argv[1]));
-       free(pts);
-
-       return JS_TRUE;
-
-err:
-       if (pts != NULL)
-               free(pts);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_polygon(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_polygon_i(cx, obj, argc, argv, rval, gdImagePolygon);
-}
-
-static JSBool
-gdimage_m_open_polygon(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_polygon_i(cx, obj, argc, argv, rval,
-           gdImageOpenPolygon);
-}
-
-static JSBool
-gdimage_m_rectangle(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_primitive5_i(cx, obj, argc, argv, rval,
-           gdImageRectangle);
-}
-
-static JSBool
-gdimage_m_filled_polygon(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_polygon_i(cx, obj, argc, argv, rval,
-           gdImageFilledPolygon);
-}
-
-static JSBool
-gdimage_m_filled_rectangle(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return gdimage_m_primitive5_i(cx, obj, argc, argv, rval,
-           gdImageFilledRectangle);
-}
-
-static JSBool
-gdimage_m_arc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             i;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 7) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       for (i = 0; i < 7; i++) {
-               if (!JSVAL_IS_INT(argv[i])) {
-                       QUEUE_EXCEPTION("Argument not an Integer");
-                       return JS_FALSE;
-               }
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageArc(img, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]),
-           JSVAL_TO_INT(argv[4]), JSVAL_TO_INT(argv[5]),
-           JSVAL_TO_INT(argv[6]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_filled_arc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             i;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 8) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       for (i = 0; i < 8; i++) {
-               if (!JSVAL_IS_INT(argv[i])) {
-                       QUEUE_EXCEPTION("Argument not an Integer");
-                       return JS_FALSE;
-               }
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageFilledArc(img, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]),
-           JSVAL_TO_INT(argv[4]), JSVAL_TO_INT(argv[5]),
-           JSVAL_TO_INT(argv[6]), JSVAL_TO_INT(argv[7]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_filled_ellipse(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_primitive5_i(cx, obj, argc, argv, rval,
-           gdImageFilledEllipse);
-}
-
-static JSBool
-gdimage_m_fill_to_border(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 4) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[3])) {
-               QUEUE_EXCEPTION("Argument 4 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageFillToBorder(img, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_fill(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageFill(img, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_set_antialiased(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageSetAntiAliased(img, JSVAL_TO_INT(argv[0]));
-
-       return JS_TRUE;
-}
-
-/*
- * Although documentation specifies that this gdImageSetAntialiasedDontBlend()
- * requires two parameters, it actually requires three.
- */
-static JSBool
-gdimage_m_set_antialiaseddontblend(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageSetAntiAliasedDontBlend(img, JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_set_brush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img, img2;
-       JSObject        *o;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       o = JSVAL_TO_OBJECT(argv[0]);
-       if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-       img2 = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-       assert(img2 != NULL);
-
-       /*
-        * Delete any previously associated GDImage property and reassign the
-        * new one so that the JS GC knows the dependency.
-        */
-       (void) JS_DeleteProperty(cx, obj, "gdimage_brush");
-       if (!JS_DefineProperty(cx, obj, "gdimage_brush", argv[0], NULL,
-           NULL, 0)) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       gdImageSetBrush(img, img2);
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_set_tile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img, img2;
-       JSObject        *o;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       o = JSVAL_TO_OBJECT(argv[0]);
-       if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-       img2 = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-       assert(img2 != NULL);
-
-       /*
-        * Delete any previously associated GDImage property and reassign the
-        * new one so that the JS GC knows the dependency.
-        */
-       (void) JS_DeleteProperty(cx, obj, "gdimage_tile");
-       if (!JS_DefineProperty(cx, obj, "gdimage_tile", argv[0], NULL, NULL,
-           0)) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       gdImageSetTile(img, img2);
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_set_style(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             *pts = NULL;
-       int             size;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if ((pts = array_to_ints_i(cx, argv[0], &size)) == NULL)
-               goto err;
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       /* The supplied array is copied as of gd v1.1.1 and up. */
-       gdImageSetStyle(img, pts, size);
-       free(pts);
-
-       return JS_TRUE;
-
-err:
-       if (pts != NULL)
-               free(pts);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_set_thickness(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageSetThickness(img, JSVAL_TO_INT(argv[0]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_alpha_blending(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_BOOLEAN(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a Boolean");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageAlphaBlending(img, (int)JSVAL_TO_BOOLEAN(argv[0]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_save_alpha(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_BOOLEAN(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a Boolean");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageSaveAlpha(img, (int)JSVAL_TO_BOOLEAN(argv[0]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_set_clip(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 4) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[3])) {
-               QUEUE_EXCEPTION("Argument 4 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageSetClip(img, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]));
-
-       return JS_TRUE;
-}
-
-/*
- * Unlike gdImageGetClip() which fills four ints via their supplied pointers,
- * this method returns an object with x1, y1, x2, y2 properties set.
- */
-static JSBool
-gdimage_m_get_clip(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-       int             x1, y1, x2, y2;
-       JSObject        *o;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageGetClip(img, &x1, &y1, &x2, &y2);
-
-       if ((o = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(o);
-       if (!JS_DefineProperty(cx, o, "x1", INT_TO_JSVAL(x1), NULL, NULL,
-           JSPROP_ENUMERATE) ||
-           !JS_DefineProperty(cx, o, "y1", INT_TO_JSVAL(y1), NULL, NULL,
-           JSPROP_ENUMERATE) ||
-           !JS_DefineProperty(cx, o, "x2", INT_TO_JSVAL(x2), NULL, NULL,
-           JSPROP_ENUMERATE) ||
-           !JS_DefineProperty(cx, o, "y2", INT_TO_JSVAL(y2), NULL, NULL,
-           JSPROP_ENUMERATE)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_alpha(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       /* A macro, so avoid side-effects */
-       v = JSVAL_TO_INT(argv[0]);
-       v = gdImageAlpha(img, v);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_get_pixel(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             v;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       v = gdImageGetPixel(img, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]));
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_bounds_safe(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             v;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       v = gdImageBoundsSafe(img, JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1]));
-       *rval = BOOLEAN_TO_JSVAL((JSBool)v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_image_sx(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       /* A macro, so avoid side-effects */
-       v = gdImageSX(img);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_image_sy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       /* A macro, so avoid side-effects */
-       v = gdImageSY(img);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-
-static JSBool
-gdimage_m_int_int3_i(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, int (*funcptr)(gdImagePtr, int, int, int))
-{
-       gdImagePtr      img;
-       int             col;
-
-       if (argc != 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       col = funcptr(img, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]));
-       *rval = INT_TO_JSVAL(col);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_int_int4_i(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, int (*funcptr)(gdImagePtr, int, int, int, int))
-{
-       gdImagePtr      img;
-       int             col;
-
-       if (argc != 4) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[3])) {
-               QUEUE_EXCEPTION("Argument 4 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       col = funcptr(img, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]));
-       *rval = INT_TO_JSVAL(col);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_color_allocate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_int_int3_i(cx, obj, argc, argv, rval,
-           gdImageColorAllocate);
-}
-
-static JSBool
-gdimage_m_color_allocate_alpha(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return gdimage_m_int_int4_i(cx, obj, argc, argv, rval,
-           gdImageColorAllocateAlpha);
-}
-
-static JSBool
-gdimage_m_color_closest(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_int_int3_i(cx, obj, argc, argv, rval,
-           gdImageColorClosest);
-}
-
-static JSBool
-gdimage_m_color_closest_alpha(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return gdimage_m_int_int4_i(cx, obj, argc, argv, rval,
-           gdImageColorClosestAlpha);
-}
-
-static JSBool
-gdimage_m_color_closest_hwb(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return gdimage_m_int_int3_i(cx, obj, argc, argv, rval,
-           gdImageColorClosestHWB);
-}
-
-static JSBool
-gdimage_m_color_exact(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_int_int3_i(cx, obj, argc, argv, rval,
-           gdImageColorExact);
-}
-
-static JSBool
-gdimage_m_color_resolve(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_int_int3_i(cx, obj, argc, argv, rval,
-           gdImageColorResolve);
-}
-
-static JSBool
-gdimage_m_color_resolve_alpha(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return gdimage_m_int_int4_i(cx, obj, argc, argv, rval,
-           gdImageColorResolveAlpha);
-}
-
-static JSBool
-gdimage_m_colors_total(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       /* A macro, so avoid side-effects */
-       v = gdImageColorsTotal(img);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_red(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       /* A macro, so avoid side-effects */
-       v = JSVAL_TO_INT(argv[0]);
-       v = gdImageRed(img, v);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_green(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       /* A macro, so avoid side-effects */
-       v = JSVAL_TO_INT(argv[0]);
-       v = gdImageGreen(img, v);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_blue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       /* A macro, so avoid side-effects */
-       v = JSVAL_TO_INT(argv[0]);
-       v = gdImageBlue(img, v);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_get_interlaced(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       int             v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       /* A macro, so avoid side-effects */
-       v = gdImageGetInterlaced(img);
-       *rval = BOOLEAN_TO_JSVAL((JSBool)v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_get_transparent(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-       int             v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       /* A macro, so avoid side-effects */
-       v = gdImageGetTransparent(img);
-       *rval = BOOLEAN_TO_JSVAL((JSBool)v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_color_deallocate(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageColorDeallocate(img, JSVAL_TO_INT(argv[0]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_color_transparent(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageColorTransparent(img, JSVAL_TO_INT(argv[0]));
-
-       return JS_TRUE;
-}
-
-
-static JSBool
-gdimage_m_char_i(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, void (*funcptr)(gdImagePtr, gdFontPtr, int, int, int, int))
-{
-       gdImagePtr      img;
-       gdFontPtr       f;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 5) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if ((f = gdfont_get(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a GDFont object");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[3])) {
-               QUEUE_EXCEPTION("Argument 4 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[4])) {
-               QUEUE_EXCEPTION("Argument 5 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       funcptr(img, f, JSVAL_TO_INT(argv[1]), JSVAL_TO_INT(argv[2]),
-           JSVAL_TO_INT(argv[3]), JSVAL_TO_INT(argv[4]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_string_i(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval,
-    void (*funcptr)(gdImagePtr, gdFontPtr, int, int, unsigned char *, int))
-{
-       gdImagePtr      img;
-       gdFontPtr       f;
-       char            *bytes;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 5) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if ((f = gdfont_get(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a GDFont object");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[3]) ||
-           (bytes = JS_GetStringBytes(JSVAL_TO_STRING(argv[3]))) == NULL) {
-               QUEUE_EXCEPTION("Argument 4 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[4])) {
-               QUEUE_EXCEPTION("Argument 5 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       funcptr(img, f, JSVAL_TO_INT(argv[1]), JSVAL_TO_INT(argv[2]), bytes,
-           JSVAL_TO_INT(argv[4]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_char(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_char_i(cx, obj, argc, argv, rval, gdImageChar);
-}
-
-static JSBool
-gdimage_m_char_up(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_char_i(cx, obj, argc, argv, rval, gdImageCharUp);
-}
-
-static JSBool
-gdimage_m_string(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_string_i(cx, obj, argc, argv, rval, gdImageString);
-}
-
-static JSBool
-gdimage_m_string_up(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return gdimage_m_string_i(cx, obj, argc, argv, rval, gdImageStringUp);
-}
-
-static JSBool
-gdimage_m_string_ft(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       char            *font, *string, *error;
-       jsdouble        ptsize, angle;
-       int             brect[8], i;
-       jsval           rect[8];
-       JSObject        *a;
-
-       if (argc != 7) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[1]) ||
-           (font = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]))) == NULL) {
-               QUEUE_EXCEPTION("Argument 2 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_NUMBER(argv[2]) ||
-           !JS_ValueToNumber(cx, argv[2], &ptsize)) {
-               QUEUE_EXCEPTION("Argument 3 not a Number");
-               goto err;
-       }
-       if (!JSVAL_IS_NUMBER(argv[3]) ||
-           !JS_ValueToNumber(cx, argv[3], &angle)) {
-               QUEUE_EXCEPTION("Argument 4 not a Number");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[4])) {
-               QUEUE_EXCEPTION("Argument 5 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[5])) {
-               QUEUE_EXCEPTION("Argument 6 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[6]) ||
-           (string = JS_GetStringBytes(JSVAL_TO_STRING(argv[6]))) == NULL) {
-               QUEUE_EXCEPTION("Argument 7 not a String");
-               goto err;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       if ((error = gdImageStringFT(img, brect, JSVAL_TO_INT(argv[0]), font,
-           (double)ptsize, (double)angle, JSVAL_TO_INT(argv[4]),
-           JSVAL_TO_INT(argv[5]), string)) != NULL) {
-               QUEUE_EXCEPTION(error);
-               goto err;
-       }
-
-       for (i = 0; i < 8; i++)
-               rect[i] = INT_TO_JSVAL(brect[i]);
-       if ((a = JS_NewArrayObject(cx, 8, rect)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(a);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_string_ft_ex(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-       char            *font, *string, *error;
-       jsdouble        ptsize, angle;
-       int             brect[8], i;
-       jsval           rect[8];
-       JSObject        *o, *a;
-       JSString        *str;
-       gdFTStringExtra ex;
-
-       ex.flags = gdFTEX_XSHOW | gdFTEX_RETURNFONTPATHNAME |
-           gdFTEX_RESOLUTION;
-       ex.hdpi = ex.vdpi = 96;
-       ex.xshow = ex.fontpath = NULL;
-
-       if (argc != 8) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[1]) ||
-           (font = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]))) == NULL) {
-               QUEUE_EXCEPTION("Argument 2 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_NUMBER(argv[2]) ||
-           !JS_ValueToNumber(cx, argv[2], &ptsize)) {
-               QUEUE_EXCEPTION("Argument 3 not a Number");
-               goto err;
-       }
-       if (!JSVAL_IS_NUMBER(argv[3]) ||
-           !JS_ValueToNumber(cx, argv[3], &angle)) {
-               QUEUE_EXCEPTION("Argument 4 not a Number");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[4])) {
-               QUEUE_EXCEPTION("Argument 5 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[5])) {
-               QUEUE_EXCEPTION("Argument 6 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[6]) ||
-           (string = JS_GetStringBytes(JSVAL_TO_STRING(argv[6]))) == NULL) {
-               QUEUE_EXCEPTION("Argument 7 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_NULL(argv[7]) && !JSVAL_IS_OBJECT(argv[7])) {
-               QUEUE_EXCEPTION("Argument 8 not Null or Object");
-               goto err;
-       }
-
-       if (!JSVAL_IS_NULL(argv[7])) {
-               JSObject        *o;
-               jsval           v;
-
-               o = JSVAL_TO_OBJECT(argv[7]);
-
-               if (JS_GetProperty(cx, o, "linespacing", &v) &&
-                   !JSVAL_IS_VOID(v)) {
-                       jsdouble        d;
-
-                       if (!JSVAL_IS_NUMBER(v) ||
-                           !JS_ValueToNumber(cx, v, &d)) {
-                               QUEUE_EXCEPTION("linespacing not a Number");
-                               goto err;
-                       }
-                       ex.linespacing = (double)d;
-                       ex.flags |= gdFTEX_LINESPACE;
-               }
-               if (JS_GetProperty(cx, o, "charmap", &v) &&
-                   !JSVAL_IS_VOID(v)) {
-                       if (!JSVAL_IS_INT(v)) {
-                               QUEUE_EXCEPTION("charmap not an Integer");
-                               goto err;
-                       }
-                       ex.charmap = JSVAL_TO_INT(v);
-                       ex.flags |= gdFTEX_CHARMAP;
-               }
-               if (JS_GetProperty(cx, o, "hdpi", &v) && !JSVAL_IS_VOID(v)) {
-                       if (!JSVAL_IS_INT(v)) {
-                               QUEUE_EXCEPTION("hdpi not an Integer");
-                               goto err;
-                       }
-                       ex.hdpi = JSVAL_TO_INT(v);
-               }
-               if (JS_GetProperty(cx, o, "vdpi", &v) && !JSVAL_IS_VOID(v)) {
-                       if (!JSVAL_IS_INT(v)) {
-                               QUEUE_EXCEPTION("vdpi not an Integer");
-                               goto err;
-                       }
-                       ex.vdpi = JSVAL_TO_INT(v);
-               }
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       if ((error = gdImageStringFTEx(img, brect, JSVAL_TO_INT(argv[0]), font,
-           (double)ptsize, (double)angle, JSVAL_TO_INT(argv[4]),
-           JSVAL_TO_INT(argv[5]), string, &ex)) != NULL) {
-               QUEUE_EXCEPTION(error);
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, NULL, NULL, NULL)) == NULL)
-               goto err2;
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if (ex.xshow != NULL) {
-               if ((str = JS_NewStringCopyZ(cx, ex.xshow)) == NULL)
-                       goto err2;
-               if (!JS_DefineProperty(cx, o, "xshow", STRING_TO_JSVAL(str),
-                   NULL, NULL, JSPROP_ENUMERATE))
-                       goto err2;
-               gdFree(ex.xshow);
-               ex.xshow = NULL;
-       }
-       if (ex.fontpath != NULL) {
-               if ((str = JS_NewStringCopyZ(cx, ex.fontpath)) == NULL)
-                       goto err2;
-               if (!JS_DefineProperty(cx, o, "fontpath", STRING_TO_JSVAL(str),
-                   NULL, NULL, JSPROP_ENUMERATE))
-                       goto err2;
-               gdFree(ex.fontpath);
-               ex.fontpath = NULL;
-       }
-
-       for (i = 0; i < 8; i++)
-               rect[i] = INT_TO_JSVAL(brect[i]);
-       if ((a = JS_NewArrayObject(cx, 8, rect)) == NULL)
-               goto err2;
-       if (!JS_DefineProperty(cx, o, "brect", OBJECT_TO_JSVAL(a), NULL, NULL,
-           JSPROP_ENUMERATE))
-               goto err2;
-
-       return JS_TRUE;
-
-err2:
-       QUEUE_EXCEPTION("Internal error!");
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (ex.xshow != NULL)
-               gdFree(ex.xshow);
-       if (ex.fontpath != NULL)
-               gdFree(ex.fontpath);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_string_ft_circle(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-       char            *font, *topstr, *botstr, *error;
-       jsdouble        radius, textradius, fillportion, ptsize;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 10) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_NUMBER(argv[2]) ||
-           !JS_ValueToNumber(cx, argv[2], &radius)) {
-               QUEUE_EXCEPTION("Argument 3 not a Number");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_NUMBER(argv[3]) ||
-           !JS_ValueToNumber(cx, argv[3], &textradius)) {
-               QUEUE_EXCEPTION("Argument 4 not a Number");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_NUMBER(argv[4]) ||
-           !JS_ValueToNumber(cx, argv[4], &fillportion)) {
-               QUEUE_EXCEPTION("Argument 5 not a Number");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[5]) ||
-           (font = JS_GetStringBytes(JSVAL_TO_STRING(argv[5]))) == NULL) {
-               QUEUE_EXCEPTION("Argument 6 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_NUMBER(argv[6]) ||
-           !JS_ValueToNumber(cx, argv[6], &ptsize)) {
-               QUEUE_EXCEPTION("Argument 7 not a Number");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[7]) ||
-           (topstr = JS_GetStringBytes(JSVAL_TO_STRING(argv[7]))) == NULL) {
-               QUEUE_EXCEPTION("Argument 8 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[8]) ||
-           (botstr = JS_GetStringBytes(JSVAL_TO_STRING(argv[8]))) == NULL) {
-               QUEUE_EXCEPTION("Argument 9 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[9])) {
-               QUEUE_EXCEPTION("Argument 10 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       if ((error = gdImageStringFTCircle(img, JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1]), (double)radius, (double)textradius,
-           (double)fillportion, font, (double)ptsize, topstr, botstr,
-           JSVAL_TO_INT(argv[9]))) != NULL) {
-               QUEUE_EXCEPTION(error);
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-
-static JSBool
-gdimage_m_copy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      src, dst;
-       JSObject        *o;
-       int             i;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 7) {
-               QUEUE_EXCEPTION("Wrong number of argumens");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       o = JSVAL_TO_OBJECT(argv[0]);
-       if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       for (i = 1; i < 7; i++) {
-               if (!JSVAL_IS_INT(argv[i])) {
-                       char    str[256];
-
-                       (void) snprintf(str, 255,
-                           "Argument %d not an Integer", i + 1);
-                       QUEUE_EXCEPTION(str);
-                       return JS_FALSE;
-               }
-       }
-
-       src = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(src != NULL);
-       dst = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-       assert(dst != NULL);
-
-       gdImageCopy(dst, src, JSVAL_TO_INT(argv[1]), JSVAL_TO_INT(argv[2]),
-           JSVAL_TO_INT(argv[3]), JSVAL_TO_INT(argv[4]),
-           JSVAL_TO_INT(argv[5]), JSVAL_TO_INT(argv[6]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_copy_resized(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      src, dst;
-       JSObject        *o;
-       int             i;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 9) {
-               QUEUE_EXCEPTION("Wrong number of argumens");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       o = JSVAL_TO_OBJECT(argv[0]);
-       if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       for (i = 1; i < 9; i++) {
-               if (!JSVAL_IS_INT(argv[i])) {
-                       char    str[256];
-
-                       (void) snprintf(str, 255,
-                           "Argument %d not an Integer", i + 1);
-                       QUEUE_EXCEPTION(str);
-                       return JS_FALSE;
-               }
-       }
-
-       src = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(src != NULL);
-       dst = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-       assert(dst != NULL);
-
-       gdImageCopyResized(dst, src, JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]),
-           JSVAL_TO_INT(argv[4]), JSVAL_TO_INT(argv[5]),
-           JSVAL_TO_INT(argv[6]), JSVAL_TO_INT(argv[7]),
-           JSVAL_TO_INT(argv[8]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_copy_resampled(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      src, dst;
-       JSObject        *o;
-       int             i;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 9) {
-               QUEUE_EXCEPTION("Wrong number of argumens");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       o = JSVAL_TO_OBJECT(argv[0]);
-       if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       for (i = 1; i < 9; i++) {
-               if (!JSVAL_IS_INT(argv[i])) {
-                       char    str[256];
-
-                       (void) snprintf(str, 255,
-                           "Argument %d not an Integer", i + 1);
-                       QUEUE_EXCEPTION(str);
-                       return JS_FALSE;
-               }
-       }
-
-       src = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(src != NULL);
-       dst = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-       assert(dst != NULL);
-
-       gdImageCopyResampled(dst, src, JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]),
-           JSVAL_TO_INT(argv[4]), JSVAL_TO_INT(argv[5]),
-           JSVAL_TO_INT(argv[6]), JSVAL_TO_INT(argv[7]),
-           JSVAL_TO_INT(argv[8]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_copy_rotated(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      src, dst;
-       JSObject        *o;
-       int             i;
-       jsdouble        dstx, dsty;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 8) {
-               QUEUE_EXCEPTION("Wrong number of argumens");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       o = JSVAL_TO_OBJECT(argv[0]);
-       if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_NUMBER(argv[1]) ||
-           !JS_ValueToNumber(cx, argv[1], &dstx)) {
-               QUEUE_EXCEPTION("Argument 2 not a Number");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_NUMBER(argv[2]) ||
-           !JS_ValueToNumber(cx, argv[2], &dsty)) {
-               QUEUE_EXCEPTION("Argument 3 not a Number");
-               return JS_FALSE;
-       }
-       for (i = 3; i < 8; i++) {
-               if (!JSVAL_IS_INT(argv[i])) {
-                       char    str[256];
-
-                       (void) snprintf(str, 255,
-                           "Argument %d not an Integer", i + 1);
-                       QUEUE_EXCEPTION(str);
-                       return JS_FALSE;
-               }
-       }
-
-       src = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(src != NULL);
-       dst = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-       assert(dst != NULL);
-
-       gdImageCopyRotated(dst, src, (double)dstx, (double)dsty,
-           JSVAL_TO_INT(argv[3]), JSVAL_TO_INT(argv[4]),
-           JSVAL_TO_INT(argv[5]), JSVAL_TO_INT(argv[6]),
-           JSVAL_TO_INT(argv[7]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_copy_merge(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      src, dst;
-       JSObject        *o;
-       int             i;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 8) {
-               QUEUE_EXCEPTION("Wrong number of argumens");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       o = JSVAL_TO_OBJECT(argv[0]);
-       if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       for (i = 1; i < 8; i++) {
-               if (!JSVAL_IS_INT(argv[i])) {
-                       char    str[256];
-
-                       (void) snprintf(str, 255,
-                           "Argument %d not an Integer", i + 1);
-                       QUEUE_EXCEPTION(str);
-                       return JS_FALSE;
-               }
-       }
-
-       src = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(src != NULL);
-       dst = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-       assert(dst != NULL);
-
-       gdImageCopyMerge(dst, src, JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]),
-           JSVAL_TO_INT(argv[4]), JSVAL_TO_INT(argv[5]),
-           JSVAL_TO_INT(argv[6]), JSVAL_TO_INT(argv[7]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_copy_merge_gray(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      src, dst;
-       JSObject        *o;
-       int             i;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 8) {
-               QUEUE_EXCEPTION("Wrong number of argumens");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       o = JSVAL_TO_OBJECT(argv[0]);
-       if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       for (i = 1; i < 8; i++) {
-               if (!JSVAL_IS_INT(argv[i])) {
-                       char    str[256];
-
-                       (void) snprintf(str, 255,
-                           "Argument %d not an Integer", i + 1);
-                       QUEUE_EXCEPTION(str);
-                       return JS_FALSE;
-               }
-       }
-
-       src = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(src != NULL);
-       dst = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-       assert(dst != NULL);
-
-       gdImageCopyMergeGray(dst, src, JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]), JSVAL_TO_INT(argv[3]),
-           JSVAL_TO_INT(argv[4]), JSVAL_TO_INT(argv[5]),
-           JSVAL_TO_INT(argv[6]), JSVAL_TO_INT(argv[7]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_palette_copy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      src, dst;
-       JSObject        *o;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of argumens");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-       o = JSVAL_TO_OBJECT(argv[0]);
-       if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               return JS_FALSE;
-       }
-
-       src = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(src != NULL);
-       dst = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-       assert(dst != NULL);
-
-       gdImagePaletteCopy(dst, src);
-
-       return JS_TRUE;
-}
-
-static JSBool
-gdimage_m_square_to_circle(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of argumens");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageSquareToCircle(img, JSVAL_TO_INT(argv[0]));
-
-       return JS_TRUE;
-}
-
-
-/*
- * Like the C function, returns a bitmap which may be compared against the
- * GD.GD_CMP_* bits.
- */
-static JSBool
-gdimage_m_compare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img1, img2;
-       JSObject        *o;
-       int             v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of argumens");
-               goto err;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               goto err;
-       }
-       o = JSVAL_TO_OBJECT(argv[0]);
-       if (!JS_InstanceOf(cx, o, &gdimage_class, NULL)) {
-               QUEUE_EXCEPTION("Argument 1 not a GDImage object");
-               goto err;
-       }
-
-       img1 = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img1 != NULL);
-       img2 = JS_GetInstancePrivate(cx, o, &gdimage_class, NULL);
-       assert(img2 != NULL);
-
-       v = gdImageCompare(img1, img2);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-gdimage_m_interlace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       gdImagePtr      img;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of argumens");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_BOOLEAN(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a Boolean");
-               return JS_FALSE;
-       }
-
-       img = JS_GetInstancePrivate(cx, obj, &gdimage_class, NULL);
-       assert(img != NULL);
-
-       gdImageInterlace(img, (int)JSVAL_TO_BOOLEAN(argv[0]));
-
-       return JS_TRUE;
-}
-
-
-/*
- * GDFont object control
- */
-
-JSObject *
-js_InitGDFontClass(JSContext *cx, JSObject *obj, JSObject *obj2)
-{
-       JSObject        *proto, *o;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &gdfont_class,
-           gdfont_constructor, 0, NULL, NULL, NULL, NULL)) == NULL)
-               return NULL;
-
-       /* Attach font objects statically to the global GD object */
-       if ((o = gdfont_new(cx, gdFontGetSmall())) != NULL)
-               JS_DefineProperty(cx, obj2, "gdFontSmall", OBJECT_TO_JSVAL(o),
-                   NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT |
-                   JSPROP_ENUMERATE);
-       if ((o = gdfont_new(cx, gdFontGetLarge())) != NULL)
-               JS_DefineProperty(cx, obj2, "gdFontLarge", OBJECT_TO_JSVAL(o),
-                   NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT |
-                   JSPROP_ENUMERATE);
-       if ((o = gdfont_new(cx, gdFontGetMediumBold())) != NULL)
-               JS_DefineProperty(cx, obj2, "gdFontMediumBold",
-                   OBJECT_TO_JSVAL(o), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_ENUMERATE);
-       if ((o = gdfont_new(cx, gdFontGetGiant())) != NULL)
-               JS_DefineProperty(cx, obj2, "gdFontGiant", OBJECT_TO_JSVAL(o),
-                   NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT |
-                   JSPROP_ENUMERATE);
-       if ((o = gdfont_new(cx, gdFontGetTiny())) != NULL)
-               JS_DefineProperty(cx, obj2, "gdFontTiny", OBJECT_TO_JSVAL(o),
-                   NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT |
-                   JSPROP_ENUMERATE);
-
-       return proto;
-}
-
-static JSBool
-gdfont_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-       QUEUE_EXCEPTION("GDFont object not user-instanciable");
-
-       return JS_FALSE;
-}
-
-static void
-gdfont_finalize(JSContext *cx, JSObject *obj)
-{
-
-       if (JS_GetInstancePrivate(cx, obj, &gdfont_class, NULL) != NULL)
-               (void) JS_SetPrivate(cx, obj, NULL);
-}
-
-static JSObject *
-gdfont_new(JSContext *cx, gdFontPtr f)
-{
-       JSObject        *o;
-
-       if (f == NULL)
-               return NULL;
-
-       if ((o = JS_NewObject(cx, &gdfont_class, NULL, NULL)) == NULL)
-               return NULL;
-
-       if (!JS_SetPrivate(cx, o, f))
-               return NULL;
-
-       return o;
-}
-
-static gdFontPtr
-gdfont_get(JSContext *cx, jsval v)
-{
-       JSObject        *o;
-       gdFontPtr       f;
-
-       if (!JSVAL_IS_OBJECT(v))
-               return NULL;
-       o = JSVAL_TO_OBJECT(v);
-
-       if (!JS_InstanceOf(cx, o, &gdfont_class, NULL))
-               return NULL;
-
-       f = JS_GetInstancePrivate(cx, o, &gdfont_class, NULL);
-       assert(f != NULL);
-
-       return f;
-}
diff --git a/mmsoftware/js/classes/js_gd.h b/mmsoftware/js/classes/js_gd.h
deleted file mode 100644 (file)
index 1294377..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id: js_gd.h,v 1.1 2006/10/24 12:42:43 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSGD_H
-#define JSGD_H
-
-#include <js_gd.h>
-
-extern JSObject        *js_InitGDClass(JSContext *, JSObject *);
-
-#endif
diff --git a/mmsoftware/js/classes/js_global.c b/mmsoftware/js/classes/js_global.c
deleted file mode 100644 (file)
index 35cdcd1..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/* $Id: js_global.c,v 1.1 2006/07/22 04:18:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Provide a means to set and access global objects and global properties.
- * Basically we can store hashtable objects, which each can store arbitrary
- * String/String tuples, but using shared memory instead of a database.
- * Internally a hash table would also be used to index hash tables by String.
- * There would be a single synchronization lock around the system.
- * We would need to initially work with an allocated buffer of shared memory,
- * which only needed pages are used.  For this, mmpool(3) could be used.
- * A pool of hash tables would be necessary, as well as one for the data
- * pair items.  To be linked among those.
- *
- * I yet have to find a proper interface.  We optionally could have stuff
- * like:
- *
- * Global.getProperty(table, property);
- * Global.setProperty(table, property, string);
- *
- * But would it also be possible to use lazy allocation such that this would
- * be possible, although of course enforcing the same internal behavior:
- *
- * Global.table.property  would be read or set as necessary.
- *
- * Or:
- * table = new Global(tablename);
- * table.prop = 'string';
- * out.put(table.prop + "\n");
- */
-
-
-
-#include <stdint.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-#include <js_global.h>
-
-
-
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-
-/*
- * Static prototypes
- */
-static JSBool  global_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    global_finalize(JSContext *, JSObject *);
-
-static JSBool  global_getProperty(JSContext *, JSObject *, jsval, jsval *);
-static JSBool  global_setProperty(JSContext *, JSObject *, jsval, jsval *);
-
-
-
-/*
- * Static globals
- */
-
-/* Global class */
-static JSClass pg_class = {
-       "Global", JCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       global_getProperty, global_setProperty, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, global_finalize
-};
-
-
-
-/*
- * Global object control
- */
-
-JSObject *
-js_InitGlobalClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &global_class,
-           global_constructor, 0, NULL, NULL, NULL, NULL)) == NULL) {
-               (void) fprintf(stderr, "Error initializing Global class\n");
-               goto err;
-       }
-
-       /* XXX Initialize shared memory and lock */
-
-       return proto;
-
-err:
-
-       return NULL;
-}
-
-static JSBool
-global_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       if (!JS_IsConstructing(cx)) {
-               QUEUE_EXCEPTION("Constructor called as a function");
-               goto err;
-       }
-
-       /* XXX */
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-global_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-
-       /* XXX */
-
-       return JS_TRUE;
-}
-
-static JSBool
-global_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-
-       /* XXX */
-
-       return JS_TRUE;
-}
diff --git a/mmsoftware/js/classes/js_global.h b/mmsoftware/js/classes/js_global.h
deleted file mode 100644 (file)
index d4fc6c1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id: js_global.h,v 1.1 2006/07/22 04:18:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSGLOBAL_H
-#define JSGLOBAL_H
-
-#include <jsapi.h>
-
-extern JSObject        *js_InitGlobalClass(JSContext *, JSObject *);
-
-#endif
diff --git a/mmsoftware/js/classes/js_mysql.c b/mmsoftware/js/classes/js_mysql.c
deleted file mode 100644 (file)
index a29becc..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-/* $Id: js_mysql.c,v 1.1 2006/07/22 04:18:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
diff --git a/mmsoftware/js/classes/js_mysql.h b/mmsoftware/js/classes/js_mysql.h
deleted file mode 100644 (file)
index 2a40bd6..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: js_mysql.h,v 1.1 2006/07/22 04:18:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSMYSQL_H
-#define JSMYSQL_H
-
-extern JSObject        *js_InitMySQLClass(JSContext *, JSObject *);
-
-#endif
diff --git a/mmsoftware/js/classes/js_pgsql.c b/mmsoftware/js/classes/js_pgsql.c
deleted file mode 100644 (file)
index 57f151d..0000000
+++ /dev/null
@@ -1,4744 +0,0 @@
-/* $Id: js_pgsql.c,v 1.12 2006/10/27 06:09:44 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * XXX TODO XXX
- * - Verify if JS_GetStringLength() really safe to continue using
- * - (maybe) make reentrant by causing optimization buffers to be part of
- *   generated objects instances's private data (using structures as necessary
- *   instead of simply wrapping around the native object's pointer
- *   (actually PGconn object).
- * - See what to do about the following functions:
- *   - PQgetssl() (returns an SSL object!)
- */
-
-
-
-#include <stdint.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-#include <libpq-fe.h>
-#include <libpq/libpq-fs.h>    /* Large Objects API */
-
-#include <js_pgsql.h>
-#include <js_file.h>
-#include <js_gcroot.h>
-
-
-
-/*
- * PostgreSQL services for ECMAScript
- *
- * NOTES:
- * We create a parent PG object which allows us to store static first-level
- * methods as well as numeric properties required to work with the libpq
- * library.  Almost all other functionality is available through PGconn and
- * PGresult objects afterwards.
- *
- * If supporting the asynchroneous part of the API, it should also be possible
- * for us to return an FD object for a PGconn * so that polling could be used,
- * etc.  Or at least just return the fd int which can be used easily to create
- * an FD object with afterwards by the caller.
- */
-
-
-
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-
-
-/*
- * Static prototypes
- */
-static int     buffer_grow(size_t);
-static int     param_grow(int);
-
-static JSBool  pg_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    pg_finalize(JSContext *, JSObject *);
-
-static JSBool  pg_sm_PQconndefaults(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pg_sm_PQconnectdb(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pg_sm_PQconnectStart(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pg_sm_PQresStatus(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pg_sm_PQunescapeBytea(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSObject        *js_InitPGconnClass(JSContext *, JSObject *);
-static JSBool  pgconn_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    pgconn_finalize(JSContext *, JSObject *);
-
-static JSBool  pgconn_m_PQfinish(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQconnectPoll(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQreset(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQresetStart(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQresetPoll(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQdb(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQuser(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQpass(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQhost(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQport(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQtty(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQoptions(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQstatus(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQtransactionStatus(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQparameterStatus(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQprotocolVersion(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQserverVersion(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQerrorMessage(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQsocket(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQbackendPID(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQexec(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQsendQuery(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQexecParams2(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, int);
-static JSBool  pgconn_m_PQexecParams(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQsendQueryParams(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQprepare2(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, int);
-static JSBool  pgconn_m_PQprepare(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQsendPrepare(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQexecPrepared2(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *, int);
-static JSBool  pgconn_m_PQexecPrepared(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQsendQueryPrepared(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQmakeEmptyPGresult(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQescapeStringConn(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQescapeByteaConn(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQgetCancel(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQnotifies(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQgetResult(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQconsumeInput(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQisBusy(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQsetnonblocking(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQisnonblocking(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQflush(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQsetErrorVerbosity(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQtrace(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQuntrace(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQputCopyData(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQputCopyEnd(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQgetCopyData(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQsetNoticeReceiver(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static void    notice_receiver(void *, const PGresult *);
-static JSBool  pgconn_m_PQsetNoticeProcessor(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static void    notice_processor(void *, const char *);
-static JSBool  pgconn_m_lo_creat(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_lo_create(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_lo_import(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_lo_export(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_lo_open(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_lo_write(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_lo_read(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_lo_lseek(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_lo_tell(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_lo_close(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_lo_unlink(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSObject        *js_InitPGresultClass(JSContext *, JSObject *);
-static JSBool  pgresult_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    pgresult_finalize(JSContext *, JSObject *);
-
-static JSBool  pgresult_m_PQclear(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQresultStatus(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgresult_m_PQresultErrorMessage(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgresult_m_PQresultErrorField(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgresult_m_PQntuples(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQnfields(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQfname(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQfnumber(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQftable(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQftablecol(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQfformat(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQftype(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQfmod(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQfsize(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQbinaryTuples(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgresult_m_PQgetvalue(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQgetisnull(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQgetlength(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQcmdStatus(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQcmdTuples(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQoidValue(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQprint(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSObject        *js_InitPGcancelClass(JSContext *, JSObject *);
-static JSBool  pgcancel_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    pgcancel_finalize(JSContext *, JSObject *);
-
-static JSBool  pgcancel_m_PQfreeCancel(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgcancel_m_PQcancel(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSObject        *js_InitPGPrintOptClass(JSContext *, JSObject *);
-static JSBool  pgprintopt_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-
-
-/*
- * Static globals
- */
-
-/*
- * General purpose string buffer (note that this is not thread-safe).
- * Allows to optimize functions such as PQescapeStringConn().
- * XXX To be thread-safe, these would need to be tied to objects rather than
- * being shared globals.  This obviously would require more memory and add
- * additional object creation overhead.
- */
-static char    *buffer = NULL;
-static size_t  buffer_size = 0;
-static Oid     *param_types = NULL;
-static char    **param_values = NULL;
-static int     *param_lengths = NULL;
-static int     *param_formats = NULL;
-static int     param_entries = 0;
-
-
-/* PG class */
-static JSClass pg_class = {
-       "PG", 0, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,
-       JS_ConvertStub, pg_finalize
-};
-
-/* Provided static methods */
-static JSFunctionSpec pg_smethods[] = {
-       { "connDefaults", pg_sm_PQconndefaults, 0, 0, 0 },
-       { "connectDb", pg_sm_PQconnectdb, 1, 0, 0 },
-       { "connectStart", pg_sm_PQconnectStart, 1, 0, 0 },
-       { "resStatus", pg_sm_PQresStatus, 1, 0, 0 },
-       { "unescapeBytea", pg_sm_PQunescapeBytea, 2, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/* Provided static properties */
-
-#define SP(n) \
-    { #n, n }
-
-static struct property_spec    pg_sprops[] = {
-       SP(PGRES_POLLING_OK),
-       SP(PGRES_POLLING_READING),
-       SP(PGRES_POLLING_WRITING),
-       SP(PGRES_POLLING_FAILED),
-       SP(PGRES_EMPTY_QUERY),
-       SP(PGRES_COMMAND_OK),
-       SP(PGRES_TUPLES_OK),
-       SP(PGRES_COPY_OUT),
-       SP(PGRES_COPY_IN),
-       SP(PGRES_BAD_RESPONSE),
-       SP(PGRES_NONFATAL_ERROR),
-       SP(PGRES_FATAL_ERROR),
-       SP(PG_DIAG_SEVERITY),
-       SP(PG_DIAG_SQLSTATE),
-       SP(PG_DIAG_MESSAGE_PRIMARY),
-       SP(PG_DIAG_MESSAGE_DETAIL),
-       SP(PG_DIAG_MESSAGE_HINT),
-       SP(PG_DIAG_STATEMENT_POSITION),
-       SP(PG_DIAG_INTERNAL_POSITION),
-       SP(PG_DIAG_INTERNAL_QUERY),
-       SP(PG_DIAG_CONTEXT),
-       SP(PG_DIAG_SOURCE_FILE),
-       SP(PG_DIAG_SOURCE_LINE),
-       SP(PG_DIAG_SOURCE_FUNCTION),
-       SP(CONNECTION_OK),
-       SP(CONNECTION_BAD),
-       SP(CONNECTION_STARTED),
-       SP(CONNECTION_MADE),
-       SP(CONNECTION_AWAITING_RESPONSE),
-       SP(CONNECTION_AUTH_OK),
-       SP(CONNECTION_SSL_STARTUP),
-       SP(CONNECTION_SETENV),
-       SP(PQTRANS_IDLE),
-       SP(PQTRANS_ACTIVE),
-       SP(PQTRANS_INTRANS),
-       SP(PQTRANS_INERROR),
-       SP(PQTRANS_UNKNOWN),
-       SP(InvalidOid),
-       SP(PQERRORS_TERSE),
-       SP(PQERRORS_DEFAULT),
-       SP(PQERRORS_VERBOSE),
-       SP(INV_READ),
-       SP(INV_WRITE),
-       SP(SEEK_SET),
-       SP(SEEK_CUR),
-       SP(SEEK_END),
-       { NULL, 0 }
-};
-
-#undef SP
-
-
-/* PGconn class */
-static JSClass pgconn_class = {
-       "PGConn", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, pgconn_finalize
-};
-
-/* Provided methods/functions */
-static JSFunctionSpec pgconn_methods[] = {
-       { "finish", pgconn_m_PQfinish, 0, 0, 0 },
-       { "connectPoll", pgconn_m_PQconnectPoll, 0, 0, 0 },
-       { "reset", pgconn_m_PQreset, 0, 0, 0 },
-       { "resetStart", pgconn_m_PQresetStart, 0, 0, 0 },
-       { "resetPoll", pgconn_m_PQresetPoll, 0, 0, 0 },
-       { "db", pgconn_m_PQdb, 0, 0, 0 },
-       { "user", pgconn_m_PQuser, 0, 0, 0 },
-       { "pass", pgconn_m_PQpass, 0, 0, 0 },
-       { "host", pgconn_m_PQhost, 0, 0, 0 },
-       { "port", pgconn_m_PQport, 0, 0, 0 },
-       { "tty", pgconn_m_PQtty, 0, 0, 0 },
-       { "options", pgconn_m_PQoptions, 0, 0, 0 },
-       { "status", pgconn_m_PQstatus, 0, 0, 0 },
-       { "transactionStatus", pgconn_m_PQtransactionStatus, 0, 0, 0 },
-       { "parameterStatus", pgconn_m_PQparameterStatus, 1, 0, 0 },
-       { "protocolVersion", pgconn_m_PQprotocolVersion, 0, 0, 0 },
-       { "serverVersion", pgconn_m_PQserverVersion, 0, 0, 0 },
-       { "errorMessage", pgconn_m_PQerrorMessage, 0, 0, 0 },
-       { "socket", pgconn_m_PQsocket, 0, 0, 0 },
-       { "backendPid", pgconn_m_PQbackendPID, 0, 0, 0 },
-       { "exec", pgconn_m_PQexec, 1, 0, 0 },
-       { "sendQuery", pgconn_m_PQsendQuery, 1, 0, 0 },
-       { "execParams", pgconn_m_PQexecParams, 7, 0, 0 },
-       { "sendQueryParams", pgconn_m_PQsendQueryParams, 7, 0, 0 },
-       { "prepare", pgconn_m_PQprepare, 4, 0, 0 },
-       { "sendPrepare", pgconn_m_PQsendPrepare, 4, 0, 0 },
-       { "execPrepared", pgconn_m_PQexecPrepared, 6, 0, 0 },
-       { "sendQueryPrepared", pgconn_m_PQsendQueryPrepared, 6, 0, 0 },
-       { "makeEmptyPGResult", pgconn_m_PQmakeEmptyPGresult, 1, 0, 0 },
-       { "escapeStringConn", pgconn_m_PQescapeStringConn, 1, 0, 0 },
-       { "escapeByteaConn", pgconn_m_PQescapeByteaConn, 1, 0, 0 },
-       { "getCancel", pgconn_m_PQgetCancel, 0, 0, 0 },
-       { "notifies", pgconn_m_PQnotifies, 0, 0, 0 },
-       { "getResult", pgconn_m_PQgetResult, 0, 0, 0 },
-       { "consumeInput", pgconn_m_PQconsumeInput, 0, 0, 0 },
-       { "isBusy", pgconn_m_PQisBusy, 0, 0, 0 },
-       { "setNonBlocking", pgconn_m_PQsetnonblocking, 1, 0, 0 },
-       { "isNonBlocking", pgconn_m_PQisnonblocking, 0, 0, 0 },
-       { "flush", pgconn_m_PQflush, 0, 0, 0 },
-       { "setErrorVerbosity", pgconn_m_PQsetErrorVerbosity, 1, 0, 0 },
-       { "trace", pgconn_m_PQtrace, 1, 0, 0 },
-       { "untrace", pgconn_m_PQuntrace, 0, 0, 0 },
-       { "putCopyData", pgconn_m_PQputCopyData, 1, 0, 0 },
-       { "putCopyEnd", pgconn_m_PQputCopyEnd, 1, 0, 0 },
-       { "getCopyData", pgconn_m_PQgetCopyData, 1, 0, 0 },
-       { "setNoticeReceiver", pgconn_m_PQsetNoticeReceiver, 2, 0, 0 },
-       { "setNoticeProcessor", pgconn_m_PQsetNoticeProcessor, 2, 0, 0 },
-       { "loCreat", pgconn_m_lo_creat, 1, 0, 0 },
-       { "loCreate", pgconn_m_lo_create, 1, 0, 0 },
-       { "loImport", pgconn_m_lo_import, 1, 0, 0 },
-       { "loExport", pgconn_m_lo_export, 2, 0, 0 },
-       { "loOpen", pgconn_m_lo_open, 2, 0, 0 },
-       { "loWrite", pgconn_m_lo_write, 2, 0, 0 },
-       { "loRead", pgconn_m_lo_read, 2, 0, 0 },
-       { "loSeek", pgconn_m_lo_lseek, 3, 0, 0 },
-       { "loTell", pgconn_m_lo_tell, 1, 0, 0 },
-       { "loClose", pgconn_m_lo_close, 1, 0, 0 },
-       { "loUnlink", pgconn_m_lo_unlink, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-
-/* PGresult class */
-static JSClass pgresult_class = {
-       "PGResult", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, pgresult_finalize
-};
-
-/* Provided methods/functions */
-static JSFunctionSpec pgresult_methods[] = {
-       { "clear", pgresult_m_PQclear, 0, 0, 0 },
-       { "resultStatus", pgresult_m_PQresultStatus, 0, 0, 0 },
-       { "resultErrorMessage", pgresult_m_PQresultErrorMessage, 0, 0, 0 },
-       { "resultErrorField", pgresult_m_PQresultErrorField, 1, 0, 0 },
-       { "nTuples", pgresult_m_PQntuples, 0, 0, 0 },
-       { "nFields", pgresult_m_PQnfields, 0, 0, 0 },
-       { "fName", pgresult_m_PQfname, 1, 0, 0 },
-       { "fNumber", pgresult_m_PQfnumber, 1, 0, 0 },
-       { "fTable", pgresult_m_PQftable, 1, 0, 0 },
-       { "fTableCol", pgresult_m_PQftablecol, 1, 0, 0 },
-       { "fFormat", pgresult_m_PQfformat, 1, 0, 0 },
-       { "fType", pgresult_m_PQftype, 1, 0, 0 },
-       { "fMod", pgresult_m_PQfmod, 1, 0, 0 },
-       { "fSize", pgresult_m_PQfsize, 1, 0, 0 },
-       { "binaryTuples", pgresult_m_PQbinaryTuples, 1, 0, 0 },
-       { "getValue", pgresult_m_PQgetvalue, 2, 0, 0 },
-       { "getIsNull", pgresult_m_PQgetisnull, 2, 0, 0 },
-       { "getLength", pgresult_m_PQgetlength, 2, 0, 0 },
-       { "cmdStatus", pgresult_m_PQcmdStatus, 0, 0, 0 },
-       { "cmdTuples", pgresult_m_PQcmdTuples, 0, 0, 0 },
-       { "oidValue", pgresult_m_PQoidValue, 0, 0, 0 },
-       { "print", pgresult_m_PQprint, 2, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-
-/* PGcancel class */
-static JSClass pgcancel_class = {
-       "PGCancel", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, pgcancel_finalize
-};
-
-/* Provided methods/functions */
-static JSFunctionSpec pgcancel_methods[] = {
-       { "freeCancel", pgcancel_m_PQfreeCancel, 0, 0, 0 },
-       { "cancel", pgcancel_m_PQcancel, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-
-/* PGPrintOpt class */
-static JSClass pgprintopt_class = {
-       "PGPrintOpt", 0, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
-       JS_FinalizeStub
-};
-
-
-
-static int
-buffer_grow(size_t required)
-{
-       size_t  new;
-       void    *ptr;
-
-       /* Account space for possible NUL */
-       if (++required <= buffer_size)
-               return 0;
-
-       for (new = buffer_size; new < required; new *= 2) ;
-
-       if ((ptr = realloc(buffer, new)) == NULL)
-               return -1;
-
-       buffer = ptr;
-       buffer_size = new;
-
-       return 0;
-}
-
-static int
-param_grow(int required)
-{
-       int     new;
-       void    *types, *values, *lengths, *formats;
-
-       /* Account space for NULL */
-       if (++required <= param_entries)
-               return 0;
-
-       for (new = param_entries; new < required; new *= 2) ;
-
-       if ((types = realloc(param_types, sizeof(Oid) * new)) == NULL ||
-           (values = realloc(param_values, sizeof(char *) * new)) == NULL ||
-           (lengths = realloc(param_lengths, sizeof(int) * new)) == NULL ||
-           (formats = realloc(param_formats, sizeof(int) * new)) == NULL)
-               return -1;
-
-       param_types = types;
-       param_values = values;
-       param_lengths = lengths;
-       param_formats = formats;
-       param_entries = new;
-
-       return 0;
-}
-
-
-/*
- * PG object control
- */
-
-JSObject *
-js_InitPGClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &pg_class, pg_constructor, 0,
-           NULL, NULL, NULL, pg_smethods)) == NULL) {
-               (void) fprintf(stderr, "Error initializing PG class\n");
-               goto err;
-       }
-
-       /* Create static properties */
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "PG: JS_GetConstructor == NULL\n");
-               goto err;
-       }
-       for (sp = pg_sprops; sp->name != NULL; sp++) {
-               if (!JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT)) {
-                       (void) fprintf(stderr,
-                           "PG: Error defining property %s\n", sp->name);
-                       goto err;
-               }
-       }
-
-       /*
-        * Initialize object/classes which we'll need to instanciate objects
-        * from
-        */
-       if (js_InitPGconnClass(cx, obj) == NULL) {
-               (void) fprintf(stderr, "PG: InitPGconnClass()\n");
-               goto err;
-       }
-       if (js_InitPGresultClass(cx, obj) == NULL) {
-               (void) fprintf(stderr, "PG: InitPGresultClass()\n");
-               goto err;
-       }
-       if (js_InitPGcancelClass(cx, obj) == NULL) {
-               (void) fprintf(stderr, "PG: InitPGcancelClass()\n");
-               goto err;
-       }
-       if (js_InitPGPrintOptClass(cx, obj) == NULL) {
-               (void) fprintf(stderr, "PG: InitPGPrintOptClass()\n");
-               goto err;
-       }
-
-       /*
-        * Note that the following buffers, although allowing optimizations,
-        * cause the functions using them to not be reentrant.  For reentrancy
-        * similar buffers could be attached to the object instances instead.
-        * This would of course however mean a larger memory footprint.
-        * If doing this, we would also need a custom structure for the
-        * private data instead of simply wrapping around the native pointers.
-        */
-
-       /* Allocate an initial general purpose buffer */
-       if ((buffer = malloc(16384)) == NULL) {
-               (void) fprintf(stderr, "PG: malloc()\n");
-               goto err;
-       }
-       buffer_size = 16384;
-
-       /* As well as buffers for the *Params() parameter arrays */
-       if ((param_types = malloc(sizeof(Oid) * 16)) == NULL ||
-           (param_values = malloc(sizeof(char *) * 16)) == NULL ||
-           (param_lengths = malloc(sizeof(int) * 16)) == NULL ||
-           (param_formats = malloc(sizeof(int) * 16)) == NULL) {
-               (void) fprintf(stderr, "PG: malloc()\n");
-               goto err;
-       }
-       param_entries = 16;
-
-       return proto;
-
-err:
-       if (buffer != NULL)
-               free(buffer);
-       if (param_types != NULL)
-               free(param_types);
-       if (param_values != NULL)
-               free(param_values);
-       if (param_lengths != NULL)
-               free(param_lengths);
-       if (param_formats != NULL)
-               free(param_formats);
-
-       return NULL;
-}
-
-/* Non instanciable */
-static JSBool
-pg_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("PG class uninstanciable");
-
-       return JS_FALSE;
-}
-
-/* ARGSUSED */
-static void
-pg_finalize(JSContext *cx, JSObject *obj)
-{
-
-       /* NOOP */
-}
-
-
-/*
- * PG object static methods
- */
-
-/*
- * Returns an array of objects which each contain the various parameters
- * returned by PQconndefaults().
- * XXX Could be more useful if it returned an object of objects using the
- * keyword as property in the first object level, perhaps.
- */
-static JSBool
-pg_sm_PQconndefaults(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PQconninfoOption        *in = NULL, *p;
-       JSObject                *array = NULL;
-       JSString                *str;
-       int                     i;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       if ((in = PQconndefaults()) == NULL) {
-               QUEUE_EXCEPTION("PQconndefaults() == NULL");
-               goto err;
-       }
-       if ((array = JS_NewArrayObject(cx, 0, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(array);
-
-#define DEFINE_STRING_PROP(n, s)       do {                            \
-       if ((str = JS_NewStringCopyZ(cx, (char *)(s))) == NULL) {       \
-               QUEUE_EXCEPTION("Out of memory!");                      \
-               goto err;                                               \
-       }                                                               \
-       if (!JS_DefineProperty(cx, o, (n), STRING_TO_JSVAL(str), NULL,  \
-           NULL, JSPROP_ENUMERATE)) {                                  \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-#define DEFINE_STRING_PROP2(n, s, l)   do {                            \
-       if ((str = JS_NewStringCopyN(cx, (char *)(s), (l))) == NULL) {  \
-               QUEUE_EXCEPTION("Out of memory!");                      \
-               goto err;                                               \
-       }                                                               \
-       if (!JS_DefineProperty(cx, o, (n), STRING_TO_JSVAL(str), NULL,  \
-           NULL, JSPROP_ENUMERATE)) {                                  \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-#define DEFINE_INT_PROP(n, i)  do {                                    \
-       if (!JS_DefineProperty(cx, array, (n), INT_TO_JSVAL((int)(i)),  \
-           NULL, NULL, JSPROP_ENUMERATE)) {                            \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-
-       /* Polulate array with objects */
-       for (i = 0, p = in; p->keyword != NULL; p++, i++) {
-               JSObject        *o;
-
-               if ((o = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
-                       QUEUE_EXCEPTION("Out of memory");
-                       goto err;
-               }
-               /* Root immediately by inserting object into array */
-               if (!JS_DefineElement(cx, array, i, OBJECT_TO_JSVAL(o),
-                   NULL, NULL, JSPROP_ENUMERATE)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-
-               /* Populate object with properties */
-               DEFINE_STRING_PROP("keyword", p->keyword);
-               DEFINE_STRING_PROP("envvar", p->envvar);
-               DEFINE_STRING_PROP("compiled", p->compiled);
-               DEFINE_STRING_PROP("val", p->val);
-               DEFINE_STRING_PROP("label", p->label);
-               DEFINE_STRING_PROP2("dispchar", p->dispchar, 1);
-               DEFINE_INT_PROP("dispsize", p->dispsize);
-       }
-
-#undef DEFINE_STRING_PROP
-#undef DEFINE_STRING_PROP2
-#undef DEFINE_INT_PROP
-
-       PQconninfoFree(in);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (in != NULL)
-               PQconninfoFree(in);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pg_sm_PQconnectdb(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc = NULL;
-       char            *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0]) ||
-           (str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &pgconn_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if ((pgc = PQconnectdb(str)) == NULL) {
-               QUEUE_EXCEPTION("PQconnectdb");
-               goto err;
-       }
-       if (!JS_SetPrivate(cx, o, pgc)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Add reverse resolve entry */
-       if (!js_map_add(pgc, cx, o, NULL)) {
-               QUEUE_EXCEPTION("js_map_add()");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgc != NULL)
-               PQfinish(pgc);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pg_sm_PQconnectStart(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc = NULL;
-       char            *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0]) ||
-           (str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       if ((o = JS_NewObject(cx, &pgconn_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if ((pgc = PQconnectStart(str)) == NULL) {
-               QUEUE_EXCEPTION("PQconnectStart");
-               goto err;
-       }
-       if (!JS_SetPrivate(cx, o, pgc)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Reverse resolve entry */
-       if (!js_map_add(pgc, cx, o, NULL)) {
-               QUEUE_EXCEPTION("js_map_add()");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgc != NULL)
-               PQfinish(pgc);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pg_sm_PQresStatus(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       char            *res;
-       JSString        *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       res = PQresStatus(JSVAL_TO_INT(argv[0]));
-       if ((str = JS_NewStringCopyZ(cx, res)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: Semantics are different from C PQunescapeBytea() in that it is
- * supplied a single String and that it returns a resulting String, or null on
- * error.  Much easier to work with within ECMAScript this way.
- */
-static JSBool
-pg_sm_PQunescapeBytea(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       JSString        *str;
-       char            *from;
-       size_t          reslen;
-       unsigned char   *res = NULL;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0]) ||
-           (from = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((res = PQunescapeBytea(from, &reslen)) == NULL) {
-               QUEUE_EXCEPTION("PQescapeByteaConn()");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, res, reslen)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       PQfreemem(res);
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       if (res != NULL)
-               PQfreemem(res);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-
-/*
- * PGconn object control
- */
-
-static JSObject *
-js_InitPGconnClass(JSContext *cx, JSObject *obj)
-{
-
-       return (JS_InitClass(cx, obj, NULL, &pgconn_class, pgconn_constructor,
-           0, NULL, pgconn_methods, NULL, NULL));
-}
-
-/* Non instanciable */
-static JSBool
-pgconn_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("PGconn class not user-instanciable");
-
-       return JS_FALSE;
-}
-
-static void
-pgconn_finalize(JSContext *cx, JSObject *obj)
-{
-       PGconn  *pgc;
-
-       if ((pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL))
-           != NULL) {
-               omap_t  *omap;
-
-               PQfinish(pgc);
-               (void) JS_SetPrivate(cx, obj, NULL);
-               if ((omap = js_map_lookup(pgc)) != NULL)
-                       js_map_remove(omap);
-       }
-}
-
-
-/*
- * PGconn object methods
- */
-
-static JSBool
-pgconn_m_PQfinish(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       if ((pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL))
-           != NULL) {
-               omap_t  *omap;
-
-               PQfinish(pgc);
-               (void) JS_SetPrivate(cx, obj, NULL);
-               if ((omap = js_map_lookup(pgc)))
-                       js_map_remove(omap);
-       }
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQconnectPoll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn                          *pgc;
-       PostgresPollingStatusType       s;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       s = PQconnectPoll(pgc);
-       *rval = INT_TO_JSVAL((int)s);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQreset(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       PQreset(pgc);
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQresetStart(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       int     ret;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       ret = PQresetStart(pgc);
-       *rval = INT_TO_JSVAL((int)ret);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQresetPoll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn                          *pgc;
-       PostgresPollingStatusType       s;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       s = PQresetPoll(pgc);
-       *rval = INT_TO_JSVAL((int)s);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQdb(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       char            *str;
-       JSString        *jstr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQdb(pgc);
-       if ((jstr = JS_NewStringCopyZ(cx, str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(jstr);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQuser(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       char            *str;
-       JSString        *jstr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQuser(pgc);
-       if ((jstr = JS_NewStringCopyZ(cx, str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(jstr);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQpass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       char            *str;
-       JSString        *jstr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQpass(pgc);
-       if ((jstr = JS_NewStringCopyZ(cx, str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(jstr);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQhost(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       char            *str;
-       JSString        *jstr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQhost(pgc);
-       if ((jstr = JS_NewStringCopyZ(cx, str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(jstr);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       char            *str;
-       JSString        *jstr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQport(pgc);
-       if ((jstr = JS_NewStringCopyZ(cx, str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(jstr);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQtty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       char            *str;
-       JSString        *jstr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQtty(pgc);
-       if ((jstr = JS_NewStringCopyZ(cx, str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(jstr);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQoptions(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       char            *str;
-       JSString        *jstr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQoptions(pgc);
-       if ((jstr = JS_NewStringCopyZ(cx, str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(jstr);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQstatus(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       ConnStatusType  s = CONNECTION_BAD;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       s = PQstatus(pgc);
-       *rval = INT_TO_JSVAL((int)s);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQtransactionStatus(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn                  *pgc;
-       PGTransactionStatusType s;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       s = PQtransactionStatus(pgc);
-       *rval = INT_TO_JSVAL((int)s);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQparameterStatus(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn          *pgc;
-       char            *param;
-       const char      *str;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0]) ||
-           (param = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Argument not a String");
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((str = PQparameterStatus(pgc, param)) != NULL) {
-               JSString        *jstr;
-
-               if ((jstr = JS_NewStringCopyZ(cx, str)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       return JS_FALSE;
-               }
-               *rval = STRING_TO_JSVAL(jstr);
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQprotocolVersion(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn  *pgc;
-       int     v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       v = PQprotocolVersion(pgc);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQserverVersion(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn  *pgc;
-       int     v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       v = PQserverVersion(pgc);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQerrorMessage(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       char            *str;
-       JSString        *jstr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQerrorMessage(pgc);
-       if ((jstr = JS_NewStringCopyZ(cx, str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(jstr);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQsocket(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       int     fd;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       fd = PQsocket(pgc);
-       *rval = INT_TO_JSVAL(fd);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQbackendPID(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       int     v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       v = PQbackendPID(pgc);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQexec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-       char            *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       if (!JSVAL_IS_STRING(argv[0]) ||
-           (str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if ((pgr = PQexec(pgc, str)) == NULL) {
-               QUEUE_EXCEPTION("PQexec()");
-               goto err;
-       }
-       if (!JS_SetPrivate(cx, o, pgr)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Record reverse resolve entry */
-       if (!js_map_add(pgr, cx, o, obj)) {
-               QUEUE_EXCEPTION("js_map_add()");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQsendQuery(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       char            *str;
-       int             v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       if (!JSVAL_IS_STRING(argv[0]) ||
-           (str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       v = PQsendQuery(pgc, str);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = INT_TO_JSVAL(0);
-
-       return JS_FALSE;
-}
-
-/*
- * A fairly hairy function.
- */
-static JSBool
-pgconn_m_PQexecParams2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, int async)
-{
-       int             nargs, i;
-       JSObject        *arrays[4], *o;
-       JSIdArray       *a = NULL;
-       Oid             *types = NULL;
-       char            **values = NULL;
-       int             *lengths = NULL;
-       int             *formats = NULL;
-       char            str[256];
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-
-       if (argc != 7) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an int");
-               goto err;
-       }
-       for (i = 2; i < 6; i++) {
-               if (JSVAL_IS_NULL(argv[i])) {
-                       arrays[i - 2] = NULL;
-                       continue;
-               }
-               if (!JSVAL_IS_OBJECT(argv[i]) ||
-                   !JS_IsArrayObject(cx,
-                   (arrays[i - 2] = JSVAL_TO_OBJECT(argv[i])))) {
-                       (void) snprintf(str, 255, "Argument %d not an Array",
-                           i + 1);
-                       QUEUE_EXCEPTION(str);
-                       goto err;
-               }
-       }
-       if (!JSVAL_IS_INT(argv[6])) {
-               QUEUE_EXCEPTION("Argument 7 not an int");
-               goto err;
-       }
-
-       /* Array arguments processing */
-       nargs = JSVAL_TO_INT(argv[1]);
-       if (nargs < 0) {
-               QUEUE_EXCEPTION("Argument 2 negative");
-               goto err;
-       }
-
-       if (arrays[0] != NULL)
-               types = param_types;
-       if (arrays[1] != NULL)
-               values = param_values;
-       if (arrays[2] != NULL)
-               lengths = param_lengths;
-       if (arrays[3] != NULL)
-               formats = param_formats;
-
-       for (i = 0; i < 4; i++) {
-               jsint   len;
-
-               if (arrays[i] == NULL)
-                       continue;
-
-               if (!JS_GetArrayLength(cx, arrays[i], &len) || len != nargs) {
-                       (void) snprintf(str, 255,
-                           "Argument %d Array not holding %d elements",
-                           i + 2, nargs);
-                       QUEUE_EXCEPTION(str);
-                       goto err;
-               }
-       }
-
-       if (param_grow(nargs) == -1) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       /* param_types */
-       if (types != NULL) {
-               jsval           id, val;
-               int             i2;
-               jsdouble        v;
-
-               o = arrays[0];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_NUMBER(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 3 Array's element %d "
-                                           "not a number", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               if (!JS_ValueToNumber(cx, val, &v)) {
-                                       QUEUE_EXCEPTION("Internal error!");
-                                       goto err;
-                               }
-                               types[i2++] = (Oid)v;
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       /* param_values */
-       if (values != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[1];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (JSVAL_IS_NULL(val)) {
-                                       values[i2++] = NULL;
-                                       continue;
-                               }
-                               if (!JSVAL_IS_STRING(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 4 Array's element %d "
-                                           "not a String", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               if ((values[i2++] = JS_GetStringBytes(
-                                   JSVAL_TO_STRING(val))) == NULL) {
-                                       QUEUE_EXCEPTION("Internal error!");
-                                       goto err;
-                               }
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       /* param_lengths */
-       if (lengths != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[2];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_INT(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 5 Array's element %d "
-                                           "not an int", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               lengths[i2++] = JSVAL_TO_INT(val);
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       /* param_formats */
-       if (formats != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[3];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_INT(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 6 Array's element %d "
-                                           "not an int", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               formats[i2++] = JSVAL_TO_INT(val);
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if (!async) {
-               char    *str;
-
-               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-
-               if ((pgr = PQexecParams(pgc, str, nargs, types,
-                   (const char * const *)values, lengths, formats,
-                   JSVAL_TO_INT(argv[6]))) == NULL) {
-                       QUEUE_EXCEPTION("PQexecParams()");
-                       goto err;
-               }
-
-               if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               /* Root immediately */
-               *rval = OBJECT_TO_JSVAL(o);
-
-               if (!JS_SetPrivate(cx, o, pgr)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               /* Reverse resolve entry */
-               if (!js_map_add(pgr, cx, o, obj)) {
-                       QUEUE_EXCEPTION("js_map_add()");
-                       goto err;
-               }
-
-       } else {
-               int     v;
-               char    *str;
-
-               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-
-               v = PQsendQueryParams(pgc, str, nargs, types,
-                   (const char * const *)values, lengths, formats,
-                   JSVAL_TO_INT(argv[6]));
-               *rval = INT_TO_JSVAL(v);
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-       if (a != NULL)
-               JS_DestroyIdArray(cx, a);
-
-       if (!async)
-               *rval = OBJECT_TO_JSVAL(NULL);
-       else
-               *rval = INT_TO_JSVAL(0);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQexecParams(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return pgconn_m_PQexecParams2(cx, obj, argc, argv, rval, 0);
-}
-
-static JSBool
-pgconn_m_PQsendQueryParams(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return pgconn_m_PQexecParams2(cx, obj, argc, argv, rval, 1);
-}
-
-static JSBool
-pgconn_m_PQprepare2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, int async)
-{
-       int             nargs, i;
-       JSObject        *array, *o;
-       JSIdArray       *a = NULL;
-       Oid             *types = NULL;
-       char            str[256];
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-
-       if (argc != 4) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an int");
-               goto err;
-       }
-       if (JSVAL_IS_NULL(argv[3]))
-               array = NULL;
-       else {
-               if (!JSVAL_IS_OBJECT(argv[3]) ||
-                   !JS_IsArrayObject(cx,
-                   (array = JSVAL_TO_OBJECT(argv[3])))) {
-                       QUEUE_EXCEPTION("Argument 4 not an Array");
-                       goto err;
-               }
-       }
-
-       /* Array arguments processing */
-       nargs = JSVAL_TO_INT(argv[2]);
-       if (nargs < 0) {
-               QUEUE_EXCEPTION("Argument 3 negative");
-               goto err;
-       }
-
-       if (array != NULL) {
-               jsint   len;
-
-               types = param_types;
-
-               if (!JS_GetArrayLength(cx, array, &len) || len != nargs) {
-                       (void) snprintf(str, 255,
-                           "Argument 4 Array not holding %d elements",
-                           nargs);
-                       QUEUE_EXCEPTION(str);
-                       goto err;
-               }
-       }
-
-       if (param_grow(nargs) == -1) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       /* param_types */
-       if (types != NULL) {
-               jsval           id, val;
-               int             i2;
-               jsdouble        v;
-
-               o = array;
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_NUMBER(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 4 Array's element %d "
-                                           "not a number", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               if (!JS_ValueToNumber(cx, val, &v)) {
-                                       QUEUE_EXCEPTION("Internal error!");
-                                       goto err;
-                               }
-                               types[i2++] = (Oid)v;
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if (!async) {
-               char    *str1, *str2;
-
-               if ((str1 = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
-                   == NULL || (str2 = JS_GetStringBytes(JSVAL_TO_STRING(
-                   argv[1]))) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-
-               if ((pgr = PQprepare(pgc, str1, str2, nargs, types)) == NULL) {
-                       QUEUE_EXCEPTION("PQprepare()");
-                       goto err;
-               }
-
-               if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               /* Root immediately */
-               *rval = OBJECT_TO_JSVAL(o);
-
-               if (!JS_SetPrivate(cx, o, pgr)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               /* Reverse resolve entry */
-               if (!js_map_add(pgr, cx, o, obj)) {
-                       QUEUE_EXCEPTION("js_map_add()");
-                       goto err;
-               }
-
-       } else {
-               int     v;
-               char    *str1, *str2;
-
-               if ((str1 = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
-                   == NULL || (str2 = JS_GetStringBytes(JSVAL_TO_STRING(
-                   argv[1]))) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-
-               v = PQsendPrepare(pgc, str1, str2, nargs, types);
-               *rval = INT_TO_JSVAL(v);
-
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-
-       if (!async)
-               *rval = OBJECT_TO_JSVAL(NULL);
-       else
-               *rval = INT_TO_JSVAL(0);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQprepare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return pgconn_m_PQprepare2(cx, obj, argc, argv, rval, 0);
-}
-
-static JSBool
-pgconn_m_PQsendPrepare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return pgconn_m_PQprepare2(cx, obj, argc, argv, rval, 1);
-}
-
-/*
- * Also rather hairy
- */
-static JSBool
-pgconn_m_PQexecPrepared2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, int async)
-{
-       int             nargs, i;
-       JSObject        *arrays[3], *o;
-       JSIdArray       *a = NULL;
-       char            **values = NULL;
-       int             *lengths = NULL;
-       int             *formats = NULL;
-       char            str[256];
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-
-       if (argc != 6) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an int");
-               goto err;
-       }
-       for (i = 2; i < 5; i++) {
-               if (JSVAL_IS_NULL(argv[i])) {
-                       arrays[i - 2] = NULL;
-                       continue;
-               }
-               if (!JSVAL_IS_OBJECT(argv[i]) ||
-                   !JS_IsArrayObject(cx,
-                   (arrays[i - 2] = JSVAL_TO_OBJECT(argv[i])))) {
-                       (void) snprintf(str, 255, "Argument %d not an Array",
-                           i + 1);
-                       QUEUE_EXCEPTION(str);
-                       goto err;
-               }
-       }
-       if (!JSVAL_IS_INT(argv[5])) {
-               QUEUE_EXCEPTION("Argument 7 not an int");
-               goto err;
-       }
-
-       /* Array arguments processing */
-       nargs = JSVAL_TO_INT(argv[1]);
-       if (nargs < 0) {
-               QUEUE_EXCEPTION("Argument 2 negative");
-               goto err;
-       }
-
-       if (arrays[0] != NULL)
-               values = param_values;
-       if (arrays[1] != NULL)
-               lengths = param_lengths;
-       if (arrays[2] != NULL)
-               formats = param_formats;
-
-       for (i = 0; i < 3; i++) {
-               jsint   len;
-
-               if (arrays[i] == NULL)
-                       continue;
-
-               if (!JS_GetArrayLength(cx, arrays[i], &len) || len != nargs) {
-                       (void) snprintf(str, 255,
-                           "Argument %d Array not holding %d elements",
-                           i + 2, nargs);
-                       QUEUE_EXCEPTION(str);
-                       goto err;
-               }
-       }
-
-       if (param_grow(nargs) == -1) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       /* param_values */
-       if (values != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[0];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (JSVAL_IS_NULL(val)) {
-                                       values[i2++] = NULL;
-                                       continue;
-                               }
-                               if (!JSVAL_IS_STRING(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 3 Array's element %d "
-                                           "not a String", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               if ((values[i2++] = JS_GetStringBytes(
-                                   JSVAL_TO_STRING(val))) == NULL) {
-                                       QUEUE_EXCEPTION("Internal error!");
-                                       goto err;
-                               }
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       /* param_lengths */
-       if (lengths != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[1];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_INT(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 4 Array's element %d "
-                                           "not an int", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               lengths[i2++] = JSVAL_TO_INT(val);
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       /* param_formats */
-       if (formats != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[2];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_INT(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 5 Array's element %d "
-                                           "not an int", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               formats[i2++] = JSVAL_TO_INT(val);
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if (!async) {
-               char    *str;
-
-               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-
-               if ((pgr = PQexecPrepared(pgc, str, nargs,
-                   (const char * const *)values, lengths, formats,
-                   JSVAL_TO_INT(argv[5]))) == NULL) {
-                       QUEUE_EXCEPTION("PQexecPrepared()");
-                       goto err;
-               }
-
-               if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               /* Root immediately */
-               *rval = OBJECT_TO_JSVAL(o);
-
-               if (!JS_SetPrivate(cx, o, pgr)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               /* Reverse resolve entry */
-               if (!js_map_add(pgr, cx, o, obj)) {
-                       QUEUE_EXCEPTION("js_map_add()");
-                       goto err;
-               }
-
-       } else {
-               int     v;
-               char    *str;
-
-               if ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-
-               v = PQsendQueryPrepared(pgc, str, nargs,
-                   (const char * const *)values, lengths, formats,
-                   JSVAL_TO_INT(argv[5]));
-               *rval = INT_TO_JSVAL(v);
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-       if (a != NULL)
-               JS_DestroyIdArray(cx, a);
-
-       if (!async)
-               *rval = OBJECT_TO_JSVAL(NULL);
-       else
-               *rval = INT_TO_JSVAL(0);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQexecPrepared(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return pgconn_m_PQexecPrepared2(cx, obj, argc, argv, rval, 0);
-}
-
-static JSBool
-pgconn_m_PQsendQueryPrepared(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return pgconn_m_PQexecPrepared2(cx, obj, argc, argv, rval, 1);
-}
-
-static JSBool
-pgconn_m_PQmakeEmptyPGresult(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if ((pgr = PQmakeEmptyPGresult(pgc, JSVAL_TO_INT(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("PQmakeEmptyPGresult()");
-               goto err;
-       }
-
-       if (!JS_SetPrivate(cx, o, pgr)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Revere resolve entry */
-       if (!js_map_add(pgr, cx, o, obj)) {
-               QUEUE_EXCEPTION("js_map_add()");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: Semantics are different from C PQescapeStringConn() in that it is
- * supplied a single String and that it returns a resulting String, or null on
- * error.  Much easier to work with within ECMAScript this way.
- */
-static JSBool
-pgconn_m_PQescapeStringConn(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn          *pgc;
-       JSString        *str;
-       char            *from;
-       size_t          len;
-       int             ret;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = JSVAL_TO_STRING(argv[0]);
-       if ((from = JS_GetStringBytes(str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       len = JS_GetStringLength(str);
-
-       if (buffer_grow((len * 2) + 2) == -1) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       len = PQescapeStringConn(pgc, buffer, from, len, &ret);
-       if (ret != 0) {
-               QUEUE_EXCEPTION("PQescapeStringConn()");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, buffer, len)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/* PQescapeString() deprecated in favor of PQescapeStringConn() */
-
-/*
- * Note: Semantics are different from C PQescapeByteaConn() in that it is
- * supplied a single String and that it returns a resulting String, or null on
- * error.  Much easier to work with within ECMAScript this way.
- */
-static JSBool
-pgconn_m_PQescapeByteaConn(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn          *pgc;
-       JSString        *str;
-       char            *from;
-       size_t          fromlen, reslen;
-       unsigned char   *res = NULL;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = JSVAL_TO_STRING(argv[0]);
-       if ((from = JS_GetStringBytes(str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       fromlen = JS_GetStringLength(str);
-
-       if ((res = PQescapeByteaConn(pgc, from, fromlen, &reslen)) == NULL) {
-               QUEUE_EXCEPTION("PQescapeByteaConn()");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, res, reslen)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       PQfreemem(res);
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       if (res != NULL)
-               PQfreemem(res);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQgetCancel(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       PGcancel        *pgcn = NULL;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((o = JS_NewObject(cx, &pgcancel_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if ((pgcn = PQgetCancel(pgc)) == NULL) {
-               QUEUE_EXCEPTION("PQgetCancel()");
-               goto err;
-       }
-       if (!JS_SetPrivate(cx, o, pgcn)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgcn != NULL)
-               PQfreeCancel(pgcn);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: Unlike C native PQnotifies(), returns null or a normal object with
- * the three properties set, rather than specifically a PQnotify object.
- */
-static JSBool
-pgconn_m_PQnotifies(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       PGnotify        *pgn = NULL;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((pgn = PQnotifies(pgc)) == NULL) {
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_TRUE;
-       }
-
-       if ((o = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if (!JS_DefineProperty(cx, o, "relname", STRING_TO_JSVAL(
-           JS_NewStringCopyZ(cx, pgn->relname)), NULL, NULL,
-           JSPROP_ENUMERATE)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       if (!JS_DefineProperty(cx, o, "be_pid", INT_TO_JSVAL(pgn->be_pid),
-           NULL, NULL, JSPROP_ENUMERATE)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       if (!JS_DefineProperty(cx, o, "extra", STRING_TO_JSVAL(
-           JS_NewStringCopyZ(cx, pgn->extra)), NULL, NULL,
-           JSPROP_ENUMERATE)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       PQfreemem(pgn);
-
-       return JS_TRUE;
-
-err:
-       if (pgn != NULL)
-               PQfreemem(pgn);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQgetResult(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((pgr = PQgetResult(pgc)) == NULL) {
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_TRUE;
-       }
-
-       if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if (!JS_SetPrivate(cx, o, pgr)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Reverse resolve entry */
-       if (!js_map_add(pgr, cx, o, obj)) {
-               QUEUE_EXCEPTION("js_map_add()");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQconsumeInput(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       int     v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       v = PQconsumeInput(pgc);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQisBusy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       int     v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       v = PQisBusy(pgc);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQsetnonblocking(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn  *pgc;
-       int     v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       v = PQsetnonblocking(pgc, JSVAL_TO_INT(argv[0]));
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQisnonblocking(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       int     v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       v = PQisnonblocking(pgc);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQflush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       int     v;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       v = PQflush(pgc);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQsetErrorVerbosity(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn  *pgc;
-       int     v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       v = PQsetErrorVerbosity(pgc, JSVAL_TO_INT(argv[0]));
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Requires a File object, which we root to ensure that it doesn't get
- * unexpectedly finalized.  We unroot any previously provided File object when
- * supplied with a new one.
- */
-static JSBool
-pgconn_m_PQtrace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       FILE            *fh;
-       JSObject        *gcroot;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if ((fh = file_fh(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a File");
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       /*
-        * Unroot previously rooted File object, if any, then root newly
-        * provided File object.
-        */
-       gcroot = js_GCRoot(cx);
-       assert(gcroot != NULL);
-       (void) JS_DeleteProperty(cx, gcroot, "trace_file_root");
-       if (!JS_DefineProperty(cx, gcroot, "trace_file_root", argv[0],
-           NULL, NULL, 0)) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       PQtrace(pgc, fh);
-
-       return JS_TRUE;
-}
-
-/*
- * We unroot any previously rooted File object supplied to trace().
- */
-static JSBool
-pgconn_m_PQuntrace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       JSObject        *gcroot;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       /*
-        * Unroot previously rooted File object
-        */
-       gcroot = js_GCRoot(cx);
-       assert(gcroot != NULL);
-       (void) JS_DeleteProperty(cx, gcroot, "trace_file_root");
-
-       PQuntrace(pgc);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQputCopyData(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       JSString        *str;
-       char            *bytes;
-       int             v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = JSVAL_TO_STRING(argv[0]);
-       if ((bytes = JS_GetStringBytes(str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       v = PQputCopyData(pgc, bytes, JS_GetStringLength(str));
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQputCopyEnd(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       int     v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0]) && !JSVAL_IS_NULL(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String or null");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       v = PQputCopyEnd(pgc, (JSVAL_IS_NULL(argv[0]) ? NULL :
-           JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))));
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: unlike native PQgetCopyData(), which returns an int but is supplied a
- * pointer to a pointer to be set, this implementation returns an object which
- * holds two elements: result (the integer) and data (null or String), to make
- * it easier to use with ECMAScript.
- */
-static JSBool
-pgconn_m_PQgetCopyData(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       char            *data = NULL;
-       int             res;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       res = PQgetCopyData(pgc, &data, JSVAL_TO_INT(argv[0]));
-
-       if ((o = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if (!JS_DefineProperty(cx, o, "result", INT_TO_JSVAL(res),
-           NULL, NULL, JSPROP_ENUMERATE)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       if (data != NULL && res > 0) {
-               if (!JS_DefineProperty(cx, o, "data", STRING_TO_JSVAL(
-                   JS_NewStringCopyN(cx, data, res)), NULL, NULL,
-                   JSPROP_ENUMERATE)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               PQfreemem(data);
-       } else {
-               if (!JS_DefineProperty(cx, o, "data", OBJECT_TO_JSVAL(NULL),
-                   NULL, NULL, JSPROP_ENUMERATE)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-       }
-
-       return JS_TRUE;
-
-err:
-       if (data != NULL)
-               PQfreemem(data);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQsetNoticeReceiver(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn  *pgc;
-
-       /*
-        * Verify if our connection object has the nr_function property set,
-        * in which case we set it as the return code.  If it doesn't have
-        * any, return null.
-        */
-       if (!JS_GetProperty(cx, obj, "nr_function", &rval[0]))
-               *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0]) ||
-           !JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(argv[0]))) {
-               QUEUE_EXCEPTION("Argument 1 not a Function Object");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[1]) && !JSVAL_IS_NULL(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Object or null");
-               return JS_FALSE;
-       }
-
-       /*
-        * Set the nr_function and nr_udata properties.  This simplifies
-        * things while ensuring that the ojects live as long as the
-        * connection object does.  We don't make them enumerable.
-        */
-       if (!JS_DefineProperty(cx, obj, "nr_function", argv[0], NULL, NULL,
-           JSPROP_READONLY | JSPROP_PERMANENT)) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (!JS_DefineProperty(cx, obj, "nr_udata", argv[1], NULL, NULL,
-           JSPROP_READONLY | JSPROP_PERMANENT)) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       /*
-        * Now set our custom notice_processor function.  We need to pass both
-        * cx and obj to it, although we can only pass a single pointer.  And
-        * we can't set obj as cx specific data, since the data must be
-        * connection specific.  Moreover, we can't store private data on the
-        * supplied function object, since the JSFunction * is set already.
-        * Moreover, JS_GetPrivate()/JS_GetInstancePrivate() both need the
-        * JSObject * AND the JSContext *!  This means that I need
-        * connection-specific udata other than PGconn *, since it would not
-        * be possible to trace back the allocated data at object
-        * finalization if we just allocated memory and provided the pointer
-        * as udata.  Unless I stored the pointer as a property in the
-        * connection object, heh.
-        */
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       (void) PQsetNoticeReceiver(pgc, notice_receiver, NULL);
-
-       return JS_TRUE;
-}
-
-static void
-notice_receiver(void *udata, const PGresult *pgr)
-{
-       omap_t  *omap;
-       jsval   args[2], ret, pgrv, nr_function, nr_udata;
-
-       omap = js_map_lookup((void *)pgr);
-       assert(omap != NULL);
-
-       /*
-        * JSContext       *cx;
-        * JSObject        *obj;                PGResult
-        * void            *udata;              PGConn JSObject *
-        */
-
-       pgrv = OBJECT_TO_JSVAL(omap->obj);
-
-       /* We call the user supplied function with the arguments:
-        * udata, PGResult object.
-        * We root the PGResult object to the PGConn meanwhile.
-        * We get out the udata and function to call from the connection
-        * object.
-        */
-       if (!JS_DefineProperty(omap->cx, omap->udata, "nr_pgresult", pgrv,
-           NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT))
-               return;
-
-       if (!JS_GetProperty(omap->cx, omap->udata, "nr_function",
-           &nr_function) || !JS_GetProperty(omap->cx, omap->udata,
-           "nr_udata", &nr_udata))
-               goto err;
-
-       args[0] = nr_udata;
-       args[1] = pgrv;
-
-       (void) JS_CallFunctionValue(omap->cx, omap->udata, nr_function, 2,
-           args, &ret);
-
-err:
-       (void) JS_DeleteProperty(omap->cx, omap->udata, "nr_pgresult");
-}
-
-static JSBool
-pgconn_m_PQsetNoticeProcessor(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn  *pgc;
-
-       /*
-        * Verify if our connection object has the np_function property set,
-        * in which case we set it as the return code.  If it doesn't have
-        * any, return null.
-        */
-       if (!JS_GetProperty(cx, obj, "np_function", &rval[0]))
-               *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[0]) ||
-           !JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(argv[0]))) {
-               QUEUE_EXCEPTION("Argument 1 not a Function Object");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[1]) && !JSVAL_IS_NULL(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Object or null");
-               return JS_FALSE;
-       }
-
-       /*
-        * Set the np_function and np_udata properties.  This simplifies
-        * things while ensuring that the ojects live as long as the
-        * connection object does.  We don't make them enumerable.
-        */
-       if (!JS_DefineProperty(cx, obj, "np_function", argv[0], NULL, NULL,
-           JSPROP_READONLY | JSPROP_PERMANENT)) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-       if (!JS_DefineProperty(cx, obj, "np_udata", argv[1], NULL, NULL,
-           JSPROP_READONLY | JSPROP_PERMANENT)) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       /*
-        * Now set our custom notice_processor function.  We need to pass both
-        * cx and obj to it, although we can only pass a single pointer.  And
-        * we can't set obj as cx specific data, since the data must be
-        * connection specific.  Moreover, we can't store private data on the
-        * supplied function object, since the JSFunction * is set already.
-        * Moreover, JS_GetPrivate()/JS_GetInstancePrivate() both need the
-        * JSObject * AND the JSContext *!  This means that I need
-        * connection-specific udata other than PGconn *, since it would not
-        * be possible to trace back the allocated data at object
-        * finalization if we just allocated memory and provided the pointer
-        * as udata.  Unless I stored the pointer as a property in the
-        * connection object, heh.
-        */
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       (void) PQsetNoticeProcessor(pgc, notice_processor, pgc);
-
-       return JS_TRUE;
-}
-
-/* Internal C notive processor handler which delegates to JS */
-static void
-notice_processor(void *udata, const char *msg)
-{
-       omap_t          *omap;
-       PGconn          *pgc;
-       jsval           args[2], ret, strv, np_function, np_udata;
-       JSString        *str;
-
-       /*
-        * The pgc pointer is passed through udata.  Lookup by pgc to obtain
-        * the corresponding PGConn JSObject * and its JSContext *.
-        */
-       pgc = udata;
-       omap = js_map_lookup(pgc);
-       assert(omap != NULL);
-
-       /*
-        * JSContext    *cx;
-        * JSObject     *obj;           PGConn
-        * void         *udata;
-        */
-
-       if ((str = JS_NewStringCopyZ(omap->cx, msg)) == NULL)
-               return;
-       strv = STRING_TO_JSVAL(str);
-
-       /*
-        * Obtain np_function and np_udata from the connection object we were
-        * supplied with, and all the function with parameters:
-        * udata, String.
-        * Temporarily root the JSString meanwhile.
-        */
-       if (!JS_DefineProperty(omap->cx, omap->obj, "np_message", strv,
-           NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT))
-               return;
-
-       if (!JS_GetProperty(omap->cx, omap->udata, "np_function",
-           &np_function) || !JS_GetProperty(omap->cx, omap->udata,
-           "np_udata", &np_udata))
-               goto err;
-
-       args[0] = np_udata;
-       args[1] = strv;
-
-       (void) JS_CallFunctionValue(omap->cx, omap->obj, np_function, 2,
-           args, &ret);
-
-err:
-       (void) JS_DeleteProperty(omap->cx, omap->obj, "np_message");
-}
-
-static JSBool
-pgconn_m_lo_creat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       Oid     oid;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       oid = lo_creat(pgc, JSVAL_TO_INT(argv[0]));
-
-       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_lo_create(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       Oid             oid;
-       jsdouble        v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_NUMBER(argv[0]) || !JS_ValueToNumber(cx, argv[0], &v)) {
-               QUEUE_EXCEPTION("Argument 1 not a number");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       oid = lo_create(pgc, (Oid)v);
-
-       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_lo_import(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       Oid             oid;
-       char            *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0]) ||
-           ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-
-       /* XXX Perform path/access sanity checking */
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       oid = lo_import(pgc, str);
-
-       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_lo_export(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       jsdouble        v;
-       char            *str;
-       int             r;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_NUMBER(argv[0]) || !JS_ValueToNumber(cx, argv[0], &v)) {
-               QUEUE_EXCEPTION("Argument 1 not a number");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[1]) ||
-           ((str = JS_GetStringBytes(JSVAL_TO_STRING(argv[1])))) == NULL) {
-               QUEUE_EXCEPTION("Argument 2 not a String");
-               goto err;
-       }
-
-       /* XXX Perform path/access sanity checking */
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       r = lo_export(pgc, (Oid)v, str);
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Unlike FD.open(), we don't wrap the provided integer descriptor into an
- * object and define read()/write() function as object methods.
- * This integer descriptor automatically becomes invalid once the transaction
- * terminates and as such doesn't require automatic finalization.
- */
-static JSBool
-pgconn_m_lo_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       jsdouble        v;
-       int             r;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_NUMBER(argv[0]) || !JS_ValueToNumber(cx, argv[0], &v)) {
-               QUEUE_EXCEPTION("Argument 1 not a number");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       r = lo_open(pgc, (Oid)v, JSVAL_TO_INT(argv[1]));
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Unlike lo_write(), does not need a length argument, since we can obtain it
- * using the JS string length.  Moreover, we convert to a string whatever type
- * of data was provided to us.
- */
-static JSBool
-pgconn_m_lo_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       JSString        *str;
-       char            *bytes;
-       size_t          size;
-       int             r;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       /* Convert argv[1] to a JSString */
-       if ((str = JS_ValueToString(cx, argv[1])) == NULL ||
-           (bytes = JS_GetStringBytes(str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       size = JS_GetStringLength(str);
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       r = lo_write(pgc, JSVAL_TO_INT(argv[0]), bytes, size);
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Unlike lo_read(), returns a JS String object rather than being provided a
- * buffer to fill.
- */
-static JSBool
-pgconn_m_lo_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       JSString        *str;
-       uint32          size;
-       int             ret;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_NUMBER(argv[1]) ||
-           !JS_ValueToECMAUint32(cx, argv[1], &size)) {
-               QUEUE_EXCEPTION("Argument 1 not a number");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if (buffer_grow((size_t)size) == -1) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       if ((ret = lo_read(pgc, JSVAL_TO_INT(argv[0]), buffer, (size_t)size))
-           < 0) {
-               QUEUE_EXCEPTION("lo_read()");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, buffer, (size_t)ret)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_lo_lseek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       int     r;
-
-       if (argc != 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       r = lo_lseek(pgc, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]),
-           JSVAL_TO_INT(argv[2]));
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_lo_tell(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       int     r;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       r = lo_tell(pgc, JSVAL_TO_INT(argv[0]));
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_lo_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       int     r;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       r = lo_close(pgc, JSVAL_TO_INT(argv[0]));
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_lo_unlink(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       jsdouble        v;
-       int             r;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_NUMBER(argv[0]) || !JS_ValueToNumber(cx, argv[0], &v)) {
-               QUEUE_EXCEPTION("Argument 1 not a number");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       r = lo_unlink(pgc, (Oid)v);
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-
-/*
- * PGresult object control
- */
-
-static JSObject *
-js_InitPGresultClass(JSContext *cx, JSObject *obj)
-{
-
-       return (JS_InitClass(cx, obj, NULL, &pgresult_class,
-           pgresult_constructor, 0, NULL, pgresult_methods, NULL, NULL));
-}
-
-/* Non instanciable */
-static JSBool
-pgresult_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("PGresult class not user-instanciable");
-
-       return JS_FALSE;
-}
-
-static void
-pgresult_finalize(JSContext *cx, JSObject *obj)
-{
-       PGresult        *pgr;
-
-       if ((pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL))
-           != NULL) {
-               omap_t  *omap;
-
-               PQclear(pgr);
-               (void) JS_SetPrivate(cx, obj, NULL);
-               if ((omap = js_map_lookup(pgr)) != NULL)
-                       js_map_remove(omap);
-       }
-}
-
-
-/*
- * PGresult object methods
- */
-
-static JSBool
-pgresult_m_PQclear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               return JS_FALSE;
-       }
-
-       if ((pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL))
-           != NULL) {
-               omap_t  *omap;
-
-               PQclear(pgr);
-               (void) JS_SetPrivate(cx, obj, NULL);
-               if ((omap = js_map_lookup(pgr)) != NULL)
-                       js_map_remove(omap);
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgresult_m_PQresultStatus(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGresult        *pgr;
-       ExecStatusType  s;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       s = PQresultStatus(pgr);
-       *rval = INT_TO_JSVAL((int)s);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgresult_m_PQresultErrorMessage(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGresult        *pgr;
-       char            *res;
-       JSString        *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       res = PQresultErrorMessage(pgr);
-       if ((str = JS_NewStringCopyZ(cx, res)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgresult_m_PQresultErrorField(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGresult        *pgr;
-       char            *res;
-       JSString        *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       res = PQresultErrorField(pgr, JSVAL_TO_INT(argv[0]));
-       if ((str = JS_NewStringCopyZ(cx, res)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQntuples(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       int             r;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       r = PQntuples(pgr);
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgresult_m_PQnfields(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       int             r;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       r = PQnfields(pgr);
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgresult_m_PQfname(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       char            *res;
-       JSString        *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       res = PQfname(pgr, JSVAL_TO_INT(argv[0]));
-       if ((str = JS_NewStringCopyZ(cx, res)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQfnumber(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       char            *str;
-       int             r;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0]) ||
-           (str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       r = PQfnumber(pgr, str);
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: Oid is a typedef to unsigned int.  Thus, we use a double object to
- * make sure that we do not loose any precision.
- */
-static JSBool
-pgresult_m_PQftable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       Oid             oid;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       oid = PQftable(pgr, JSVAL_TO_INT(argv[0]));
-
-       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQftablecol(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       int             r;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       r = PQftablecol(pgr, JSVAL_TO_INT(argv[0]));
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: we possibly could return a boolean value instead of an integer
- * but the documentation says that other values are reserved for possible
- * future use.  I am surprised that they do not return enumerated values.
- */
-static JSBool
-pgresult_m_PQfformat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       int             r;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       r = PQfformat(pgr, JSVAL_TO_INT(argv[0]));
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: Oid is a typedef to unsigned int.  Thus, we use a double object to
- * make sure that we do not loose any precision.
- */
-static JSBool
-pgresult_m_PQftype(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       Oid             oid;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       oid = PQftype(pgr, JSVAL_TO_INT(argv[0]));
-
-       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQfmod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       int             r;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       r = PQfmod(pgr, JSVAL_TO_INT(argv[0]));
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQfsize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       int             r;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       r = PQfsize(pgr, JSVAL_TO_INT(argv[0]));
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQbinaryTuples(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGresult        *pgr;
-       int             r;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       r = PQbinaryTuples(pgr);
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-}
-
-/*
- * Note: The semantics of PGresult.PQgetvalue() is different from the actual
- * libpq C function PQgetvalue() in that we return null on NULL fields, and
- * that we always return either the binary or text data into the field as a
- * String (since ECMAScript Strings objects allow NUL characters).
- */
-static JSBool
-pgresult_m_PQgetvalue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       JSString        *str;
-       char            *res;
-       int             row, col;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       row = JSVAL_TO_INT(argv[0]);
-       col = JSVAL_TO_INT(argv[1]);
-
-       if (PQgetisnull(pgr, row, col)) {
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_TRUE;
-       }
-
-       if ((res = PQgetvalue(pgr, row, col)) == NULL) {
-               QUEUE_EXCEPTION("PQgetvalue() == NULL");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, res, PQgetlength(pgr, row, col)))
-           == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: unlike the C PQgetisnull() function, which returns 0 or 1, we return
- * true or false, since ECMAScript supports booleans.
- * Moreover, one no longer needs to call this function in JS if it is to
- * subsequently use PQgetvalue(), since ours can return null.
- * May still be useful in some situations.
- */
-static JSBool
-pgresult_m_PQgetisnull(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       JSBool          v;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       v = PQgetisnull(pgr, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]));
-       *rval = BOOLEAN_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQgetlength(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       int             r;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       r = PQgetlength(pgr, JSVAL_TO_INT(argv[0]), JSVAL_TO_INT(argv[1]));
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQcmdStatus(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       JSString        *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       if ((str = JS_NewStringCopyZ(cx, PQcmdStatus(pgr))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-}
-
-/*
- * We could return a double easily, but like the C API are returning a string
- */
-static JSBool
-pgresult_m_PQcmdTuples(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       JSString        *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       if ((str = JS_NewStringCopyZ(cx, PQcmdTuples(pgr))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-}
-
-/*
- * Note: Oid is a typedef to unsigned int.  Thus, we use a double object to
- * make sure that we do not loose any precision.
- */
-static JSBool
-pgresult_m_PQoidValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       Oid             oid;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       oid = PQoidValue(pgr);
-
-       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * XXX Not reentrant as it uses a global buffer.
- * For simplicity, we currently use param_grow() and param_values.
- */
-static JSBool
-pgresult_m_PQprint(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       FILE            *fh;
-       JSObject        *o;
-       PQprintOpt      opt;
-       jsval           v;
-       JSIdArray       *a = NULL;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if ((fh = file_fh(cx, argv[0])) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a File");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_OBJECT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not a PGPrintOpt");
-               return JS_FALSE;
-       }
-       o = JSVAL_TO_OBJECT(argv[1]);
-       if (!JS_InstanceOf(cx, o, &pgprintopt_class, NULL)) {
-               QUEUE_EXCEPTION("Argument 2 not a PGPrintOpt");
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       /* Fill opt according to supplied object properties */
-
-       /* Boolean properties */
-       if (!JS_GetProperty(cx, o, "header", &v) || !JSVAL_IS_BOOLEAN(v)) {
-               QUEUE_EXCEPTION("property 'header' not a Boolean");
-               return JS_FALSE;
-       }
-       opt.header = JSVAL_TO_BOOLEAN(v);
-
-       if (!JS_GetProperty(cx, o, "align", &v) || !JSVAL_IS_BOOLEAN(v)) {
-               QUEUE_EXCEPTION("property 'align' not a Boolean");
-               return JS_FALSE;
-       }
-       opt.align = JSVAL_TO_BOOLEAN(v);
-
-       if (!JS_GetProperty(cx, o, "standard", &v) || !JSVAL_IS_BOOLEAN(v)) {
-               QUEUE_EXCEPTION("property 'standard' not a Boolean");
-               return JS_FALSE;
-       }
-       opt.standard = JSVAL_TO_BOOLEAN(v);
-
-       if (!JS_GetProperty(cx, o, "html3", &v) || !JSVAL_IS_BOOLEAN(v)) {
-               QUEUE_EXCEPTION("property 'html3' not a Boolean");
-               return JS_FALSE;
-       }
-       opt.html3 = JSVAL_TO_BOOLEAN(v);
-
-       if (!JS_GetProperty(cx, o, "expanded", &v) || !JSVAL_IS_BOOLEAN(v)) {
-               QUEUE_EXCEPTION("property 'expanded' not a Boolean");
-               return JS_FALSE;
-       }
-       opt.expanded = JSVAL_TO_BOOLEAN(v);
-
-       if (!JS_GetProperty(cx, o, "pager", &v) || !JSVAL_IS_BOOLEAN(v)) {
-               QUEUE_EXCEPTION("property 'pager' not a Boolean");
-               return JS_FALSE;
-       }
-       opt.pager = JSVAL_TO_BOOLEAN(v);
-
-       /* String properties */
-       if (!JS_GetProperty(cx, o, "fieldSep", &v) || !JSVAL_IS_STRING(v)) {
-               QUEUE_EXCEPTION("property 'fieldSep' not a String");
-               return JS_FALSE;
-       }
-       if ((opt.fieldSep = JS_GetStringBytes(JSVAL_TO_STRING(v))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       if (!JS_GetProperty(cx, o, "tableOpt", &v) || !JSVAL_IS_STRING(v)) {
-               QUEUE_EXCEPTION("property 'tableOpt' not a String");
-               return JS_FALSE;
-       }
-       if ((opt.tableOpt = JS_GetStringBytes(JSVAL_TO_STRING(v))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       if (!JS_GetProperty(cx, o, "caption", &v) || !JSVAL_IS_STRING(v)) {
-               QUEUE_EXCEPTION("property 'caption' not a String");
-               return JS_FALSE;
-       }
-       if ((opt.caption = JS_GetStringBytes(JSVAL_TO_STRING(v))) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               return JS_FALSE;
-       }
-
-       /* String Array property */
-       if (!JS_GetProperty(cx, o, "fieldName", &v) || !JSVAL_IS_OBJECT(v)) {
-               QUEUE_EXCEPTION("property 'fieldName' not an Array");
-               return JS_FALSE;
-       }
-       o = JSVAL_TO_OBJECT(v);
-       if (!JS_IsArrayObject(cx, o)) {
-               QUEUE_EXCEPTION("property 'fieldName' not an Array");
-               return JS_FALSE;
-       }
-       {
-               jsint len;
-
-               if (!JS_GetArrayLength(cx, o, &len)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       return JS_FALSE;
-               }
-               if (len == 0)
-                       opt.fieldName = NULL;
-               else {
-                       if (param_grow(len) == -1) {
-                               QUEUE_EXCEPTION("Out of memory!");
-                               return JS_FALSE;
-                       }
-                       opt.fieldName = param_values;
-               }
-       }
-       if (opt.fieldName != NULL) {
-               jsval   id;
-               int     i, i2;
-               char    str[256];
-
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       return JS_FALSE;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &v) &&
-                           !JSVAL_IS_VOID(v)) {
-                               if (JSVAL_IS_NULL(v) || !JSVAL_IS_STRING(v)) {
-                                       (void) snprintf(str, 255,
-                                           "fieldName Array element %d "
-                                           "not a String", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               if ((opt.fieldName[i2++] = JS_GetStringBytes(
-                                   JSVAL_TO_STRING(v))) == NULL) {
-                                       QUEUE_EXCEPTION("Internal error!");
-                                       goto err;
-                               }
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-               opt.fieldName[i2] = NULL;
-       }
-
-       /* Finally call our function */
-       PQprint(fh, pgr, &opt);
-
-       return JS_TRUE;
-
-err:
-       if (a != NULL)
-               JS_DestroyIdArray(cx, a);
-
-       return JS_FALSE;
-}
-
-
-/*
- * PGcancel object control
- */
-
-static JSObject *
-js_InitPGcancelClass(JSContext *cx, JSObject *obj)
-{
-
-       return (JS_InitClass(cx, obj, NULL, &pgcancel_class,
-           pgcancel_constructor, 0, NULL, pgcancel_methods, NULL, NULL));
-}
-
-/* Non instanciable */
-static JSBool
-pgcancel_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("PGcancel class not user-instanciable");
-
-       return JS_FALSE;
-}
-
-static void
-pgcancel_finalize(JSContext *cx, JSObject *obj)
-{
-       PGcancel        *pgc;
-
-       if ((pgc = JS_GetInstancePrivate(cx, obj, &pgcancel_class, NULL))
-           != NULL) {
-               PQfreeCancel(pgc);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-}
-
-
-/*
- * PGcancel object methods
- */
-
-static JSBool
-pgcancel_m_PQfreeCancel(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGcancel        *pgc;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               return JS_FALSE;
-       }
-
-       if ((pgc = JS_GetInstancePrivate(cx, obj, &pgcancel_class, NULL))
-           != NULL) {
-               PQfreeCancel(pgc);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgcancel_m_PQcancel(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGcancel        *pgc;
-       char            *str;
-       size_t          len;
-       JSString        *s;
-       int             r;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgcancel_class, NULL);
-       assert(pgc != NULL);
-
-       s = JSVAL_TO_STRING(argv[0]);
-       if ((str = JS_GetStringBytes(s)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       len = JS_GetStringLength(s);
-
-       r = PQcancel(pgc, str, len);
-       *rval = INT_TO_JSVAL(r);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-
-/*
- * PGPrintOpt object control
- */
-static JSObject *
-js_InitPGPrintOptClass(JSContext *cx, JSObject *obj)
-{
-       JSObject        *proto;
-       JSString        *str;
-       JSObject        *array;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &pgprintopt_class,
-           pgprintopt_constructor, 0, NULL, NULL, NULL, NULL)) == NULL)
-               return NULL;
-
-       /*
-        * Add default properties to this object's prototype
-        */
-       if (!JS_DefineProperty(cx, proto, "header", BOOLEAN_TO_JSVAL(JS_TRUE),
-               NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT) ||
-           !JS_DefineProperty(cx, proto, "align", BOOLEAN_TO_JSVAL(JS_TRUE),
-               NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT) ||
-           !JS_DefineProperty(cx, proto, "standard",
-               BOOLEAN_TO_JSVAL(JS_FALSE), NULL, NULL,
-               JSPROP_ENUMERATE | JSPROP_PERMANENT) ||
-           !JS_DefineProperty(cx, proto, "html3", BOOLEAN_TO_JSVAL(JS_FALSE),
-               NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT) ||
-           !JS_DefineProperty(cx, proto, "expanded",
-               BOOLEAN_TO_JSVAL(JS_FALSE), NULL, NULL,
-               JSPROP_ENUMERATE | JSPROP_PERMANENT) ||
-           !JS_DefineProperty(cx, proto, "pager", BOOLEAN_TO_JSVAL(JS_FALSE),
-               NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT))
-               return NULL;
-
-       if ((str = JS_NewStringCopyZ(cx, " | ")) == NULL)
-               return NULL;
-       if (!JS_DefineProperty(cx, proto, "fieldSep", STRING_TO_JSVAL(str),
-           NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT))
-               return NULL;
-
-       if ((str = JS_NewStringCopyZ(cx, "")) == NULL)
-               return NULL;
-       if (!JS_DefineProperty(cx, proto, "tableOpt", STRING_TO_JSVAL(str),
-           NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT))
-               return NULL;
-
-       if ((str = JS_NewStringCopyZ(cx, "")) == NULL)
-               return NULL;
-       if (!JS_DefineProperty(cx, proto, "caption", STRING_TO_JSVAL(str),
-           NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT))
-               return NULL;
-
-       if ((array = JS_NewArrayObject(cx, 0, NULL)) == NULL)
-               return NULL;
-       if (!JS_DefineProperty(cx, proto, "fieldName", OBJECT_TO_JSVAL(array),
-           NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT))
-               return NULL;
-
-       return proto;
-}
-
-static JSBool
-pgprintopt_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       if (!JS_IsConstructing(cx)) {
-               QUEUE_EXCEPTION("PGPrintOpt constuctor called as a function");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
diff --git a/mmsoftware/js/classes/js_pgsql.h b/mmsoftware/js/classes/js_pgsql.h
deleted file mode 100644 (file)
index b9e2878..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id: js_pgsql.h,v 1.1 2006/07/22 04:18:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSPGSQL_H
-#define JSPGSQL_H
-
-#include <jsapi.h>
-
-extern JSObject        *js_InitPGClass(JSContext *, JSObject *);
-
-#endif
diff --git a/mmsoftware/js/classes/js_signal.c b/mmsoftware/js/classes/js_signal.c
deleted file mode 100644 (file)
index 7ba66cf..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/* $Id: js_signal.c,v 1.1 2006/07/22 04:18:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Basic UNIX signal services for ECMAScript
- *
- * XXX
- * I have to see what interface I want to export. There are several
- * possibilities we could use:
- * - Have the shell register signal handlers fore interesting events at
- *   startup and allow scripts to provide a handler function, which if
- *   exists upon reception of a signal, gets executed.  We might then
- *   need to add extra custom checks in the shell for special signals
- *   which if the script doesn't end, might still end the process
- *   i.e. function would be expected to cause the script to exit upon
- *   reception of a SIGTERM signal...
- * - Provide a sigaction-style interface so that the script would be
- *   able to define functions to execute upon reception of certain
- *   signals, or null or such for the signal to be ignored.
- *   This solution might allow better application customization.
- *   If assuming this interface, the following would be exported:
- *   - Signal class, through which static signal properties could be
- *     accessed for signal numbers I.E. Signal.SIGTERM.
- *   - A static method to create/set/unset/ignore a signal/handler
- *     Signal.sigaction()?
- *     It could be provided with the parameters:
- *     Signal.sigaction(FD.SIG*, obj);
- *      Where obj would contain fields sa_handler, sa_mask, sa_flags?
- *     Signal.kill(pid, sig);
- *     Signal.sigaltstack(...) ?
- *     Signal.sigprocmask(...)
- *     Signal.sigsuspend(mask)
- *    And maybe provide the sigsetops(3)?  We possibly could just allow an
- *    array or such instead of sigset_t though if wanted.
- *    I'm not sure I want to provide sigsetjmp()/siglongjmp(). JavaScript has
- *    exceptions anyways.  If allowing sigaltstack(), C would need to allocate
- *    the stacks, so a stack object would need to be exported or such.  I
- *    don't think I want to support this as it's probably not needed by any of
- *    the applications I'll write, I don't want to write a threading library
- *    in JS.
- * - I wonder if it would be safe to invoke a JS function in a signal handler.
- *   If it wasn't, I could simply queue the signal events and then call the
- *   functions for the queue in normal process context.
- *   If doing this, sigaction has to be called to catch any signal the
- *   application wishes, and we would be rolling our own signal handling,
- *   so if wanted we could potentially provide another interface than
- *   sigaction to ECMAScript...
- */
-
-
-
-#include <sys/types.h>
-
-#include <assert.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-
-
-/* Utility macros */
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-
-/* Prototypes */
-static JSBool  signal_sm_strerror(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-
-
-/* Actual class parameters */
-static JSClass signal_class = {
-       "Signal", 0, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
-};
-
-/* Provided static methods */
-static JSFunctionSpec signal_smethods[] = {
-       { "strerror", signal_sm_strerror, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/*
- * Provided static properties.
- * We use these to provide ECMAScript with the ability to use system-specific
- * standard C constant macros without us having to tidiously map them
- * individually, or to require other scripts to be used as headers to define
- * them.  Another possibility would have been to supply these parameters as
- * string, but this would have required even slower remapping because of the
- * parsing and string comparisions.
- * We only include those which we consider necessary for now, others may be
- * added easily as needed, provided that they are added in all three maps.
- * I might perhaps develop macros and/or functions to map all these easily
- * from a single map.
- */
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-#define SP(n) \
-    { #n, n }
-
-static struct property_spec    signal_sprops[] = {
-       SP(SIGHUP),
-       SP(SIGINT),
-       SP(SIGQUIT),
-       SP(SIGILL),
-       SP(SIGTRAP),
-       SP(SIGABRT),
-       SP(SIGEMT),
-       SP(SIGFPE),
-       SP(SIGKILL),
-       SP(SIGBUS),
-       SP(SIGSEGV),
-       SP(SIGSYS),
-       SP(SIGPIPE),
-       SP(SIGALRM),
-       SP(SIGTERM),
-       SP(SIGURG),
-       SP(SIGSTOP),
-       SP(SIGTSTP),
-       SP(SIGCONT),
-       SP(SIGCHLD),
-       SP(SIGTTIN),
-       SP(SIGTTOU),
-       SP(SIGIO),
-       SP(SIGXCPU),
-       SP(SIGXFSZ),
-       SP(SIGVTALRM),
-       SP(SIGPROF),
-       SP(SIGWINCH),
-       SP(SIGINFO),
-       SP(SIGUSR1),
-       SP(SIGUSR2),
-       SP(SIGPWR),
-
-       { NULL, 0 }
-};
-
-#undef SP
-
-
-
-/*
- * Class control functions
- */
-
-JSObject *
-js_InitSignalClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &signal_class, NULL,
-           0, NULL, NULL, NULL, signal_smethods)) == NULL) {
-               (void) fprintf(stderr, "Error initializing Signal class\n");
-               return NULL;
-       }
-
-       /* Create static properties */
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "Signal: JS_GetConstructor == NULL\n");
-               return NULL;
-       }
-       for (sp = signal_sprops; sp->name != NULL; sp++) {
-               if (JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT) == JS_FALSE) {
-                       (void) fprintf(stderr,
-                           "Signal: Error defining property %s\n", sp->name);
-                       return NULL;
-               }
-       }
-
-       return proto;
-}
-
-
-
-/*
- * Static properties functions
- */
-
-
-
-/*
- * Static methods
- */
-
-static JSBool
-signal_sm_strerror(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       int             error;
-       JSString        *string;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(*argv)) {
-               QUEUE_EXCEPTION("Argument not an integer");
-               return JS_FALSE;
-       }
-       error = (int)JSVAL_TO_INT(*argv);
-
-       if ((string = JS_NewStringCopyZ(cx, "testXXX")) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               return JS_FALSE;
-       }
-
-       *rval = STRING_TO_JSVAL(string);
-
-       return JS_TRUE;
-}
diff --git a/mmsoftware/js/classes/js_signal.h b/mmsoftware/js/classes/js_signal.h
deleted file mode 100644 (file)
index a393ed1..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: js_signal.h,v 1.1 2006/07/22 04:18:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSSIGNAL_H
-#define JSSIGNAL_H
-
-extern JSObject        *js_InitSignalClass(JSContext *, JSObject *);
-
-#endif
diff --git a/mmsoftware/js/classes/js_syslog.c b/mmsoftware/js/classes/js_syslog.c
deleted file mode 100644 (file)
index 16c13b4..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-/* $Id: js_syslog.c,v 1.1 2006/10/28 22:00:43 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <sys/types.h>
-
-#include <stdint.h>
-
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-
-#include <jsapi.h>
-
-#include <js_syslog.h>
-
-
-
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-#define SP(n) \
-    { #n, n }
-
-
-
-/*
- * Static prototypes
- */
-static JSBool  syslog_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    syslog_finalize(JSContext *, JSObject *);
-
-static JSBool  syslog_sm_open(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  syslog_sm_close(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  syslog_sm_setmask(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  syslog_sm_mask(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  syslog_sm_mask_upto(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  syslog_sm_log(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-
-
-/*
- * Static globals
- */
-
-/* Syslog class */
-static JSClass syslog_class = {
-       "Syslog", 0, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
-       syslog_finalize
-};
-
-/* Provided methods */
-static JSFunctionSpec syslog_smethods[] = {
-       { "open", syslog_sm_open, 3, 0, 0 },
-       { "close", syslog_sm_close, 0, 0, 0 },
-       { "setMask", syslog_sm_setmask, 1, 0, 0 },
-       { "mask", syslog_sm_mask, 1, 0, 0 },
-       { "maskUpto", syslog_sm_mask_upto, 1, 0, 0 },
-       { "log", syslog_sm_log, 2, 0, 0 },
-       { NULL, NULL, 0, 0, 0 },
-};
-
-/* Static properties */
-
-static struct property_spec    syslog_sprops[] = {
-       SP(LOG_EMERG),
-       SP(LOG_ALERT),
-       SP(LOG_CRIT),
-       SP(LOG_ERR),
-       SP(LOG_WARNING),
-       SP(LOG_NOTICE),
-       SP(LOG_INFO),
-       SP(LOG_DEBUG),
-
-       SP(LOG_CONS),
-       SP(LOG_NDELAY),
-       SP(LOG_PERROR),
-       SP(LOG_PID),
-
-       SP(LOG_AUTH),
-       SP(LOG_AUTHPRIV),
-       SP(LOG_CRON),
-       SP(LOG_DAEMON),
-       SP(LOG_FTP),
-       SP(LOG_KERN),
-       SP(LOG_LPR),
-       SP(LOG_MAIL),
-       SP(LOG_NEWS),
-       SP(LOG_SYSLOG),
-       SP(LOG_USER),
-       SP(LOG_UUCP),
-       SP(LOG_LOCAL0),
-       SP(LOG_LOCAL1),
-       SP(LOG_LOCAL2),
-       SP(LOG_LOCAL3),
-       SP(LOG_LOCAL4),
-       SP(LOG_LOCAL5),
-       SP(LOG_LOCAL6),
-       SP(LOG_LOCAL7),
-       { NULL, 0 }
-};
-
-
-
-/*
- * Syslog object control
- */
-
-JSObject *
-js_InitSyslogClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &syslog_class,
-           syslog_constructor, 0, NULL, NULL, NULL, syslog_smethods))
-           == NULL) {
-               (void) fprintf(stderr, "Error initializing Syslog class\n");
-               goto err;
-       }
-
-       /* Create static properties. */
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "Syslog: JS_GetConstructor == NULL\n");
-               return NULL;
-       }
-       for (sp = syslog_sprops; sp->name != NULL; sp++) {
-               if (JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT) == JS_FALSE) {
-                       (void) fprintf(stderr,
-                           "Syslog: Error defining property %s\n", sp->name);
-                       return NULL;
-               }
-       }
-
-       return proto;
-
-err:
-       return NULL;
-}
-
-static JSBool
-syslog_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("Not user instanciable");
-       return JS_FALSE;
-}
-
-static void
-syslog_finalize(JSContext *cx, JSObject *obj)
-{
-
-       /* NOOP */
-}
-
-
-
-/* Static methods */
-static JSBool
-syslog_sm_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       char    *id;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0]) ||
-           (id = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an Integer");
-               return JS_FALSE;
-       }
-
-       openlog(id, JSVAL_TO_INT(argv[1]), JSVAL_TO_INT(argv[2]));
-
-       return JS_TRUE;
-}
-
-static JSBool
-syslog_sm_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       closelog();
-
-       return JS_TRUE;
-}
-
-static JSBool
-syslog_sm_setmask(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       int     v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       v = setlogmask(JSVAL_TO_INT(argv[0]));
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-syslog_sm_mask(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       int     v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       v = JSVAL_TO_INT(argv[0]);
-       v = LOG_MASK(v);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-syslog_sm_mask_upto(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       int     v;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               goto err;
-       }
-
-       v = JSVAL_TO_INT(argv[0]);
-       v = LOG_UPTO(v);
-       *rval = INT_TO_JSVAL(v);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-syslog_sm_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       char    *str;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an Integer");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[1]) ||
-           (str = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]))) == NULL) {
-               QUEUE_EXCEPTION("Argument 2 not a String");
-               return JS_FALSE;
-       }
-
-       syslog(JSVAL_TO_INT(argv[0]), "%s", str);
-
-       return JS_TRUE;
-}
diff --git a/mmsoftware/js/classes/js_syslog.h b/mmsoftware/js/classes/js_syslog.h
deleted file mode 100644 (file)
index 99cd5b8..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id: js_syslog.h,v 1.1 2006/10/28 22:00:43 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSSYSLOG_H
-#define JSSYSLOG_H
-
-#include <jsapi.h>
-
-extern JSObject        *js_InitSyslogClass(JSContext *, JSObject *);
-
-#endif
diff --git a/mmsoftware/js/js-appserv/app/test/handle.js b/mmsoftware/js/js-appserv/app/test/handle.js
deleted file mode 100644 (file)
index acaebbe..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* $Id: handle.js,v 1.1 2006/08/20 06:58:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This function handles every request, provided with session id and
- * request object.
- */
-function handle(req)
-{
-       /* XXX Only test for now */
-       var o = {result: true, req: req, msg: "NOOP test"};
-       fd.put(o.toSource() + "\r\n");
-
-       return true;
-}
-
-/* Perform application-specific saving before connection close */
-function handle_close()
-{
-       /* XXX */
-}
diff --git a/mmsoftware/js/js-appserv/app/test/main.js b/mmsoftware/js/js-appserv/app/test/main.js
deleted file mode 100644 (file)
index 7c013d6..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-/* $Id: main.js,v 1.2 2006/10/28 08:34:21 mmondor Exp $ */
-
-/*
- * Copyright (C) 2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Test application for js-appserv.
- * See the mmserver2(3) man page for more details.
- *
- * All of these functions should be provided, although they may optionally
- * be empty.
- */
-
-/*
- * TODO:
- * - js-appserv should export C->js functions to:
- *   - create SIDs
- *   - import and export single line JSON-like objects in a safe and efficient
- *     manner
- *   - Access shared memory hash tables and properties (maybe)
- *   - Log events
- *   - Create contexts, and cache/load/execute scripts within the wanted
- *     context
- * - Probably also use some config.js
- * - Define all details of the protocol, allowed request types, etc.
- *   - Should include ping/pong functionality for extended idle persistent
- *     connections
- *   - Should have a maximum delay where if no requests are received but
- *     session not yet expired, session data be saved and connection freed
- *     for other requests
- *   - Reconsider if using HTTP 1.1 with Keep-Alive would be justified.
- *     Despite that the protocol is lame (unidirectional, doesn't allow
- *     pings, awkward etc), this would permit to use simple proxy support
- *     already existing in some HTTPds...
- *   - Would be nice if we also allow logging of errors (stderr?) back to
- *     the main HTTPd, perhaps, like fcgi does.
- * - Write/modify an HTTPd to support this protocol
- *   - Also provide a routes or such system
- *   - Provide load balancing among several js-appserv daemons, as well as
- *     failover
- * - Add optional JS debugging support for development phases which can be
- *   disabled for production, possibly via a special server socket, or
- *   via an application for use from HTTP
- * - Import lithium's js preprocessor code or write mine
- * - Import lithium's web application framework or write mine
- * - Implement a cooperative client and server-side rfc2945 or hmac auth
- *   system
- * - Add authentication support for wanted HTTPd only to use the system
- * - Add optional compression and encryption between the HTTPd and the
- *   js-appserv.  If doing this, we'll need to provide read/write/flush
- *   wrappers to JS.
- * - Add stderr to logfile option
- */
-
-ilibprefix = '/home/mmondor/work/mmondor/mmsoftware/js/jslib/';
-iappprefix = '/home/mmondor/work/mmondor/mmsoftware/js/js-appserv/app/test/';
-hello_timeout = 30000;
-request_timeout = 180000;
-database = "dbname=test";
-sid_expiration = 30;
-
-
-
-function file_read(file)
-{
-       var contents = '';
-       var data = '';
-       var fd;
-
-       try {
-               fd = new FD();
-               fd.open(file, FD.O_RDONLY);
-               for (;;) {
-                       data = fd.read(65536);
-                       if (data.length == 0)
-                               break;
-                       contents += data;
-               }
-       } catch (x) {
-               stderr.write(x + "\n");
-       } finally {
-               fd.close();
-       }
-
-       return contents;
-}
-
-
-
-eval(file_read(ilibprefix + "fd.js"));
-eval(file_read(ilibprefix + "pgsql.js"));
-eval(file_read(ilibprefix + "string.js"));
-eval(file_read(ilibprefix + "json.js"));
-eval(file_read(iappprefix + "session.js"));
-eval(file_read(iappprefix + "handle.js"));
-
-
-
-/*
- * Control for the children server processes
- */
-
-/* Called when a new child process is created before serving requests */
-function child_init_hook()
-{
-       try {
-               /* Set pgc globally */
-               pgc = PG.connectDb(database);
-       } catch (x) {
-               stderr.write(x + "\n");
-       }
-       sid_init();
-}
-
-/* Called before the child process exists (interrupted or not) */
-function child_exit_hook()
-{
-       sid_gc();               /* XXX Not an ideal place for this */
-       sid_finish();
-       pgc.finish();
-}
-
-/* Called upon SIGALRM signal events (recursion-protected) */
-function child_sigalrm_hook()
-{
-       /* XXX Handle application specific timers with this */
-}
-
-
-/*
- * Control for handling clients
- */
-
-/* Called if client has to be rejected for <reason> */
-function reject_handler(r, reason)
-{
-       var o;
-
-       try {
-               fd = new FD();
-               fd.binit(r.client_socket, hello_timeout, hello_timeout);
-       } catch (x) {
-               stderr.write(x + "\n");
-       }
-
-       try {
-               o = {result: false, msg: "Rejected", reason: reason};
-               fd.put(o.toSource() + "\r\n");
-       } catch (x) {
-               stderr.write(x + "\n");
-       }
-}
-
-/* Called before closing request connection, rejected/interrupted or not */
-function request_close_hook(r)
-{
-       if (SID != undefined && DATA != undefined) {
-               /* Call application specific save hook if any */
-               if (handle_close != undefined)
-                       handle_close();
-               /* Save SID state */
-               sid_save(SID, DATA);
-               SID = undefined;
-               DATA = undefined;
-       }
-}
-
-/*
- * Called if our application allows SIGHUP or SIGTERM to interrupt currently
- * active requests, upon reception of such signal event, before closing
- */
-function request_interrupt_hook(r)
-{
-       /* XXX */
-}
-
-/* Normal client request handling function */
-function request_handler(r)
-{
-       var line;
-       var o;
-       var session;
-       var request;
-
-       try {
-               fd = new FD();
-               fd.binit(r.client_socket, hello_timeout, hello_timeout);
-       } catch (x) {
-               stderr.write(x + "\n");
-       }
-
-       o = {result: true, msg: "Ready"};
-       fd.put(o.toSource() + "\r\n");
-
-       /* Listen for incoming requests for that session */
-       for (;;) {
-               if ((line = fd.breadline(16384, true)) == null) {
-                       o = {result: false, msg: fd.berrorStr[fd.berror]};
-                       fd.put(o.toSource() + "\r\n");
-                       return;
-               }
-               try {
-                       request = json_parse(line, 10);
-                       if (request == undefined)
-                               throw(json_error);
-               } catch (x) {
-                       o = {result: false, msg: "Malformed request", x: x};
-                       fd.put(o.toSource() + "\r\n");
-                       return;
-               }
-               try {
-                       /* Handle a few special system requests */
-                       if (request.cmd == 'sid_create') {
-                               if (SID != undefined) {
-                                       o = {result: false,
-                                           msg: "Already serving a SID"};
-                                       fd.put(o.toSource() + "\r\n");
-                                       continue;
-                               }
-                               if ((o = sid_create(sid_expiration))
-                                   == undefined) {
-                                       o = {result: false,
-                                           msg: "Error creating SID"};
-                                       fd.put(o.toSource() + "\r\n");
-                                       continue;
-                               }
-                               SID = o.sid;
-                               EXPIRES = o.expires;
-                               DATA = {};
-                               o = {result: true, msg: "Created", sid: SID};
-                               fd.btimeouts(request_timeout, request_timeout);
-                               fd.put(o.toSource() + "\r\n");
-                               continue;
-                       } else if (request.cmd == 'sid_destroy' &&
-                           request.sid != undefined) {
-                               if (request.sid != SID) {
-                                       o = {result: false,
-                                           msg: "Not current SID"};
-                                       fd.put(o.toSource() + "\r\n");
-                                       continue;
-                               }
-                               sid_destroy(SID);
-                               SID = undefined;
-                               EXPIRES = undefined;
-                               DATA = undefined;
-                               o = {result: true, msg: "SID interrupted"};
-                               fd.put(o.toSource() + "\r\n");
-                               return;
-                       } else if (request.cmd == 'sid_load' &&
-                           request.sid != undefined &&
-                           request.sid.length == 64) {
-                               if (SID != undefined) {
-                                       o = {result: false,
-                                           msg: "Already serving a SID"};
-                                       fd.put(o.toSource() + "\r\n");
-                                       continue;
-                               }
-                               if ((o = sid_load(request.sid)) == undefined) {
-                                       o = {result: false,
-                                           msg: "Error loading SID data"};
-                                       fd.put(o.toSource() + "\r\n");
-                                       continue;
-                               } else {
-                                       SID = request.sid;
-                                       EXPIRES = o.expires;
-                                       DATA = o.data;
-                                       o = {result: true,
-                                           msg: "SID data loaded"};
-                                       fd.btimeouts(request_timeout,
-                                           request_timeout);
-                                       fd.put(o.toSource() + "\r\n");
-                                       continue;
-                               }
-                       } else if (request.cmd == 'ping') {
-                               o = {result: true, msg: "Pong"};
-                               fd.put(o.toSource() + "\r\n");
-                               continue;
-                       } else if (request.cmd == 'quit') {
-                               o = {result: true, msg:
-                                   (SID != undefined ? "SID data saved" :
-                                   "Closing")};
-                               fd.put(o.toSource() + "\r\n");
-                               return;
-                       }
-
-                       /*
-                        * We should only go beyond this point if serving
-                        * a valid, unexpired SID.
-                        */
-                       if (SID == undefined || DATA == undefined) {
-                               o = {result: true, msg: "No active SID"};
-                               fd.put(o.toSource() + "\r\n");
-                               continue;
-                       }
-                       if (EXPIRES < Date.parse(new Date)) {
-                               o = {result: false, msg: "SID expired"};
-                               fd.put(o.toSource() + "\r\n");
-                               return;
-                       }
-
-                       /* Handle user application requests */
-                       if (!handle(request)) {
-                               /* Destroy SID */
-                               if (SID != undefined) {
-                                       sid_destroy(SID);
-                                       SID = undefined;
-                                       EXPIRES = undefined;
-                                       DATA = undefined;
-                               }
-                               o = {result: false, command: "delete"};
-                               fd.put(o.toSource() + "\r\n");
-                               return;
-                       }
-               } catch (x) {
-                       o = {result: false, msg: "Application error",
-                           exception: x};
-                       fd.put(o.toSource() + "\r\n");
-               }
-       }
-}
diff --git a/mmsoftware/js/js-appserv/app/test/session.js b/mmsoftware/js/js-appserv/app/test/session.js
deleted file mode 100644 (file)
index aea1cf1..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/* $Id: session.js,v 1.1 2006/08/20 06:58:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Code to manage sessions and session-specific persistent data
- *
- * session table should be as follows:
- *
- * CREATE TABLE session (
- *     sid     bytea           NOT NULL,
- *     expires timestamp       NOT NULL,
- *     valid   boolean         NOT NULL DEFAULT true,
- *     busy    boolean         NOT NULL DEFAULT true,
- *     data    text            NOT NULL DEFAULT '({})',
- *     PRIMARY KEY (sid)
- * );
- *
- * sid         consists of a 64-bytes case-sensitive ASCII session ID.
- * expires     specifies the time at which this sid stops being valid.
- * valid       specifies if this sid is still valid, to invalidate before
- *             expiration, such as when logging out.
- * busy                specifies that this sid is currently being served by a
- *             process, useful when using distributed appserv on multiple
- *             boxes.
- * data                contains a string, resulting of DATA.toSource(), to hold
- *             the user session-specific persistent data.
- */
-
-
-
-var SID = undefined;
-var DATA = {};
-
-
-
-/*
- * Application initialization
- */
-function sid_init()
-{
-       var pgr;
-
-       try {
-               sid_rnd = new FD();
-               sid_rnd.open('/dev/urandom', FD.O_RDONLY);
-       } catch (x) {
-               /* XXX */
-       }
-
-       /* valid = true, busy = true */
-       pgr = pgc.prepare("sid_create",
-           "INSERT INTO session (sid, expires) " +
-           "VALUES($1, 'now'::timestamp + $2)",
-           2, null);
-       pgr.clear();
-
-       pgr = pgc.prepare("sid_load1",
-           "UPDATE session SET busy = true WHERE sid = $1 " +
-           "AND expires >= 'now'::timestamp " +
-           "AND valid = true AND busy = false",
-           1, null);
-       pgr.clear();
-       pgr = pgc.prepare("sid_load2",
-           "SELECT expires::timestamp(0),data FROM session WHERE sid = $1",
-           1, null);
-       pgr.clear();
-
-       pgr = pgc.prepare("sid_save",
-           "UPDATE session SET data = $2, busy = false WHERE sid = $1",
-           2, null);
-       pgr.clear();
-
-       pgr = pgc.prepare("sid_destroy",
-           "UPDATE session SET valid = false, busy = false WHERE sid = $1",
-           1, null);
-       pgr.clear();
-
-       pgr = pgc.prepare("sid_gc",
-           "DELETE FROM session WHERE " +
-           "expires < 'now'::timestamp " +
-           "OR valid = false",
-           0, null);
-       pgr.clear();
-
-       sid_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
-           'abcdefghijklmnopqrstuvwxyz' +
-           '0123456789-_';
-       sid_chars = sid_chars.split('');
-}
-
-/*
- * Application cleanup
- */
-function sid_finish()
-{
-
-       sid_rnd.close();
-}
-
-/*
- * Generate and create new SID, making it active (busy).
- * Returns an object, containing:
- * <sid> new sid
- * <expires> expiration timestamp in milliseconds (to compare against current
- * time in milliseconds).
- */
-function sid_create(exp)
-{
-       var rval;
-       var pgr;
-       var sid;
-       var i;
-       var o = {};
-
-       /*
-        * XXX Should be done from C for efficiency and to avoid needing so
-        * many bytes off urandom(4).
-        */
-       try {
-               rval = sid_rnd.read(64);
-       } catch (x) {
-               /* XXX */
-       }
-       sid = '';
-       /* This is apparently slower for some reason
-       for (i = 0; i < 64; i++)
-               sid += sid_chars.charAt(rval.charCodeAt(i) % 64);
-        */
-       rval = rval.split('');
-       for (i = 0; i < 64; i++)
-               sid += sid_chars[rval[i].charCodeAt() % 64];
-
-       o.expires = Date.parse(new Date) + (exp * 60000);
-
-       pgr = pgc.execPrepared("sid_create",
-           2, [sid, exp + 'minutes'], [64, 0], [1, 0], 0);
-       if (pgr.resultStatus() != PG.PGRES_COMMAND_OK)
-               sid = undefined;
-       pgr.clear();
-
-       if (sid == undefined)
-               o = undefined;
-       else
-               o.sid = sid;
-
-       return o;
-}
-
-/*
- * Load SID if still valid not already busy, and mark it busy.
- * Returns an object containing:
- * <data> the imported session-specific data
- * <expires> the expiration timstamp in milliseconds (to be compared against
- * current time in milliseconds).
- */
-function sid_load(sid)
-{
-       var pgr1, pgr2;
-       var s;
-       var o = {};
-
-       pgr1 = pgc.execPrepared("sid_load1", 1, [sid], [64], [1], 0);
-       if (pgr1.resultStatus() == PG.PGRES_COMMAND_OK &&
-           pgr1.cmdTuples() == 1) {
-               pgr2 = pgc.execPrepared("sid_load2", 1, [sid], [64], [1], 0);
-               if (pgr2.resultStatus() == PG.PGRES_TUPLES_OK &&
-                   pgr2.nTuples() == 1) {
-                       o.expires = Date.parse(pgr2.getValue(0, 0).replace(
-                           /-/g, '/'));
-                       s = 'o.data = ' + pgr2.getValue(0, 1);
-                       eval(s);
-               } else
-                      o = undefined;
-               pgr2.clear();
-       } else
-              o = undefined;
-       pgr1.clear();
-
-       return o;
-}
-
-/*
- * Save/close SID and unmark busy flag
- */
-function sid_save(sid, o)
-{
-       var pgr;
-       var s;
-
-       s = pgc.escapeStringConn(o.toSource());
-       pgr = pgc.execPrepared("sid_save", 2,
-           [sid, s], [64, s.length], [1, 0], 0);
-       pgr.clear();
-}
-
-/*
- * Close SID, unmark busy flag and invalidate it
- */
-function sid_destroy(sid)
-{
-       var pgr;
-
-       pgr = pgc.execPrepared("sid_destroy", 1, [sid], [64], [1], 0);
-       pgr.clear();
-}
-
-/*
- * Delete all expired or invalid unbusy SIDs.
- * To be called at spaced intervals.
- */
-function sid_gc()
-{
-       var pgr;
-
-       pgr = pgc.execPrepared("sid_gc", 0, null, null, null, 0);
-       pgr.clear();
-}
diff --git a/mmsoftware/js/js-appserv/app/test/test.conf b/mmsoftware/js/js-appserv/app/test/test.conf
deleted file mode 100644 (file)
index 85b7e9f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-SCRIPT_PATH    "/home/mmondor/work/mmondor/mmsoftware/js/js-appserv/app/test/main.js"
-LISTEN_TO      "0.0.0.0:8100"
-PROCTITLE      "test"
-USER           "mmondor"
-GROUPS         "users"
-PID_PATH       "/tmp/js-appserv_test.pid"
-LOCK_PATH      "/tmp/js-appserv_test.lock"
-SHLOCKS_PATH   "/tmp/js-appserv_test.lock"
diff --git a/mmsoftware/js/js-appserv/doc/js-appserv-protocol.lyx b/mmsoftware/js/js-appserv/doc/js-appserv-protocol.lyx
deleted file mode 100644 (file)
index e1789d5..0000000
+++ /dev/null
@@ -1,871 +0,0 @@
-#LyX 1.3 created this file. For more info see http://www.lyx.org/
-\lyxformat 221
-\textclass article
-\language english
-\inputencoding auto
-\fontscheme default
-\graphics default
-\paperfontsize default
-\spacing single 
-\papersize letterpaper
-\paperpackage a4
-\use_geometry 0
-\use_amsmath 0
-\use_natbib 0
-\use_numerical_citations 0
-\paperorientation portrait
-\secnumdepth 3
-\tocdepth 3
-\paragraph_separation indent
-\defskip medskip
-\quotes_language english
-\quotes_times 2
-\papercolumns 1
-\papersides 1
-\paperpagestyle default
-
-\layout Title
-
-The JS-AppServ Protocol (JSASP)
-\layout Author
-
-By Matthew Mondor
-\layout Abstract
-
-The FastCGI protocol, although bearing significant advantages over plain
- old CGI, and even often over HTTP-specific APIs, was considered an overly
- complex protocol after an in-depth study.
- Using binary format headers would not have been a problem by itself, but
- representing multiple-octets words as separate octet fields instead of
- using a big-endian representation, as well as using multiple header structure
- types depending on the size of the data to be processed, instead of a fixed
- sized word of the maximum needed size, seemed bad design.
-\layout Abstract
-
-Moreover, although this could be for the sake of flexibility, the numerous
- ways to design server-side applications with FastCGI also can lead to problems.
- Ultimately, the use of FastCGI appears most efficient with a heavily threaded
- language such as Java, which language and threaded methodology have their
- own set of problems.
- Having the HTTPd launch application-server-side processes was also considered
- unadequate.
-\layout Abstract
-
-This protocol is specifically designed to work on unix systems using an
- independent, persistent process per user session, along with long-lasting
- bidirectional socket connections between those persistent processes and
- the HTTP daemon which initiates the requests.
- This document describes the very details of the system.
- For convenience, the 
-\noun on 
-JSON
-\noun default 
- (
-\noun on 
-JavaScript Object Notation
-\noun default 
-) is used to transmit requests and responses.
-\layout Abstract
-
-Disdadventages exist; For instance this system is not compatible with the
- existing CGI or FastCGI protocols.
- Moreover, although parts could be re-implemented to support other languages,
- the system was specifically made for use with the SpiderMonkey JavaScript
- engine.
- However, a provided compatible HTTPd is included as part of the system,
- which is especially tailored to this model.
-\layout Abstract
-\pagebreak_top 
-
-\begin_inset LatexCommand \tableofcontents{}
-
-\end_inset 
-
-
-\layout Section
-\pagebreak_top 
-HTTPd specification
-\layout Subsection
-
-Model
-\layout Standard
-
-Within this system, the HTTP server model is simple and only requires a
- single process.
- Non-blocking I/O is used and the server merely serves as a proxy between
- the js-appserv servers and the remote HTTP clients.
-\layout Standard
-
-This service should be as efficient as possible, since it must avoid becoming
- a main bottleneck.
- It should ideally be written in C and care should be taken to ensure that
- no memory leaks or security problems are found.
- Nevertheless, a re-spawner process could restart this service whenever
- it dies or locks, if this situation ever was to occur.
- If it is stable enough, the active session IDs and associated information
- can be kept in RAM instead of having to be stored into a database.
- It then remains up to the dynamic application to, as necessary, save database
- information associated with this state if needed and to retreive it, etc.
-\layout Standard
-
-Optionally, the HTTPd can remember the client IP address associated with
- the create SIDs to only keep accepting requests for that SID from that
- very address, depending on the nature of the application.
-\layout Subsection
-
-Operations
-\layout Standard
-
-Here are the steps performed by the HTTP server when it obtains a request
- from a user:
-\layout Itemize
-
-Verification weither the vhost/path combination was defined by the administrator
- as being handled by a particular js-appserv application.
- If not, serve static pages as requested if they exist and are accessible.
-\layout Itemize
-
-If path corresponds to an application and that the user did not provide
- a unique session ID cookie which is still considered valid, generate a
- new session ID for the user and send along an HTTP cookie to the client,
- redirecting it to the same URL it requested with a few seconds of delay.
-\layout Itemize
-
-If path corresponds to an application and that the client provides us a
- unique session ID which still is valid, verify if there already was an
- established socket connection for this particular client/application pair.
- If so, direct request to that application.
- Otherwise, attempt to establish a socket connection to an application,
- and then forward the request there.
- The connection to the application remains open to serve further requests.
-\layout Itemize
-
-In the event where the session ID expires, or that the application initiates
- a command to discard the session ID, the corresponding socket connection
- to the application is closed and the entry for the session data is deleted.
-\layout Itemize
-
-In the event where the connection to an application is lost unexpectedly
- or as the result of an inactivity timeout and that the session did not
- expire, the session is marked as no longer having a connection, so that
- it can be re-established on the next session.
- It becomes the responsibility of the application to gracefully retrieve
- the persistent session associated data as needed so that a session may
- still resume normally.
-\layout Subsection
-
-Current implementation
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Section
-
-Application (JS-AppServ) specification
-\layout Subsection
-
-Model
-\layout Standard
-
-The server uses a multi-processes model, along with a pool of pre-forked
- processes for performance (Apache 1.3.x style).
- Basically, there is a master controller process, along with a number of
- children processes listening on the specified bound interface(s) and port(s),
- serialization being used among them.
-\layout Standard
-
-These processes expect lenghty persistent connections originating from the
- HTTP server, and generally survive after disconnection so that multiple
- connections may be served without needing a process to be restarted everytime.
- However, they can be configured to recycle after a number of connections
- were served, in order to avoid long term resources leaks.
- It is also possible for the process to exit as the result of an 
-\emph on 
-execve(2)
-\emph default 
- call being completed in the same process, in which case it immediately
- gets replaced by a new process.
-\layout Standard
-
-This model simplifies application design, avoiding the requirement of reentrant,
- thread-safe, non-blocking and leakless code to be used, which can require
- a considerable time to properly write and debug.
- Moreover, it provides more security than using a single process, avoiding
- a crash or exploit from propagating to the whole application.
- Using a multi-processes model also allows additional tricks such as privilege
- separation if the application requires this.
-\layout Standard
-
-js-appserv applications can run remotely from the HTTPd, or locally.
- Moreover, it may run under other user credentials.
- It can also run into a 
-\emph on 
-chroot(2)
-\emph default 
- environment, sandboxed using 
-\emph on 
-systrace(1)
-\emph default 
-, etc.
- Simple authentication is performed between the HTTPd and the js-appserv
- daemons when the connections are initiated, in order to prevent unwanted
- local or remote users from accessing the service.
-\emph on 
-Under local unix domain sockets, it is possible to authenticate using AF_LOCAL
- ancillary data to determine that only the allowed user(s) can connect (XXX
- to be implemented).
-\layout Standard
-
-Just like with FastCGI or other proxying distribution methods, it is still
- important for the administrator to ensure that as few as possible entry
- points are allowed.
- This can be done by making the applications listen to an interface/port
- combination to which only the HTTP server can connect, through a route
- on which sniffing is considered impractical.
-\layout Standard
-
-
-\emph on 
-Optional data stream compression and encryption between the server and the
- application will be provided, using a proprietary private key cryptography
- method which is simpler although more efficient than SSL (XXX to be implemented
-).
-
-\emph default 
- Care is taken to not disclose the password over the connection and to not
- reuse existing encryption session keys.
- There however is no guarentee whatsoever as to the security of the system.
-\layout Subsection
-
-Operations
-\layout Standard
-
-A typical js-appserv application child process behaves as follows:
-\layout Itemize
-
-Setup the JS context, loading the application scripts, preprocessing them
- (can be done by the parent process and inherited by the children, telling
- children to recycle upon reloading when signalled with 
-\emph on 
-SIGHUP
-\emph default 
-).
- Note that in-progress connections can either be interrupted upon reception
- of 
-\emph on 
-SIGHUP
-\emph default 
- by the parent, or notified to exit whenever closing normally, depending
- on the application requirements.
- This is configurable via a configuration file.
-\layout Itemize
-
-Listen for a connection until one can be obtained.
-\layout Itemize
-
-Authenticate client/HTTPd, and drop it with an error immediately if it should
- not be allowed, returning to connection waiting again.
-\layout Itemize
-
-Connection was accepted.
- Retrieve SID and previously saved session persistent data if resuming,
- or create a new SID depending on the context.
- If loading, persistent session saved data is retrieved as well for unexpired,
- valid SIDs.
-\layout Itemize
-
-The JS application now waits for requests and serves them.
- These are expected to all be requests to serve the same user (under the
- same SID).
- Therefore it is possible to cache a lot of data for efficiency.
-\layout Itemize
-
-The application can send a response to discard the session ID and then exit,
- causing the connection to be dropped and process to wait again for connections.
- It can also drop the connection for inactivity timeout.
- When closing connection for a still valid SID, persistent data is saved
- to allow resuming under another connection (which generally will be served
- by another process which will need to reload this data).
-\emph on 
-It is also possible for the application to use application-global shared
- memory to cache some SID specific data (XXX to be implemented).
-\layout Itemize
-
-From time to time, the process will exit after serving a certain number
- of persistent connections, to release dangling resources that it may be
- leaking, if any.
-\layout Itemize
-
-The application manages the session-specific unique IDs, which the HTTP
- translates to a cookie, 
-\emph on 
-GET
-\emph default 
- or 
-\emph on 
-POST
-\emph default 
- variable.
- In this protocol, these IDs (Session ID or SID) consist of 64 character
- strings which each character consists of one of a list of 64 characters.
- As such, these can be efficiently generated using a reliable random source
- of 32-bit or 64-bit input values, to generate batches of 4 to 8 characters
- at a time of the SID.
-\emph on 
-A noonce is also used so that it is unlikely for two identical SIDs to ever
- be used (XXX to be implemented).
-\layout Subsection
-
-Current implementation
-\layout Subsubsection
-
-JS-AppServ core
-\layout Standard
-
-The core of the server is writtein in C and uses the 
-\emph on 
-mmserver2(3)
-\emph default 
- library, which easily allows support for IPv4, IPv6, 
-\emph on 
-AF_LOCAL
-\emph default 
- and a pool of processes.
- This library calls application-specific callbacks, which in turn, delegate
- to JavaScript functions, allowing the application to be written into JS.
- The tasks which were considered to be best written in C for efficiency
- were exported as JS objects for use by the js-appserv application's scripts.
-\layout Standard
-
-The parent process initializes a JS runtime and context, loads in the main
- application script (
-\emph on 
-main.js
-\emph default 
-) and executes it to create the JS functions.
- This context is inherited (
-\emph on 
-MAP_COPY
-\emph default 
-) to the children processes.
- This means that multiple connections within a process can be served under
- the same context, although because of the nature of SpiderMonkey, which
- includes a good Garbage Collector, and the fact that between connections
- we clear 
-\emph on 
-SID
-\emph default 
- and 
-\emph on 
-DATA
-\emph default 
-, this should generally not be a problem, and it increases efficiency.
-
-\emph on 
- However, hooks are provided to the scripts so that they may load and cache
- scripts and then execute them under different contexts as needed (XXX to
- be implemented).
-\layout Subsubsection
-
-JS-AppServ Web applications
-\layout Standard
-
-Once in the 
-\emph on 
-Request Server State
-\emph default 
- (
-\begin_inset LatexCommand \ref{sub:The-request-server}
-
-\end_inset 
-
-), the non-system requests are forwarded to JS functions provided by the
- custom user Web application.
-\emph on 
-This system may dispatch operations under various contexts as necessary.
-\layout Standard
-
-XXX
-\layout Section
-
-The JS-AppServ protocol (JSASP)
-\layout Standard
-
-Here we define the JSASP.
-\layout Subsection
-
-Overview
-\layout Standard
-
-The use of the 
-\noun on 
-JSON
-\noun default 
- (
-\noun on 
-JavaScript Object Notation
-\noun default 
-) format was chosen for its simplicity and efficiency, using a simple custom
- protocol, over other approaches often using XML and HTTP, or complex proprietar
-y binary formats.
- A custom JSON parser was implemented in order to avoid needing to use the
- insecure 
-\emph on 
-eval()
-\emph default 
- function.
-\layout Standard
-
-The JSASP allows the applications to run independently from the HTTP daemon
- and to be distributed as necessary among various servers as application
- load requirements increase.
- It permits the HTTPd to create and maintain sessions and perform requests
- on behalf of a session to serve a user.
-\layout Standard
-
-These session-specific requests, similarily as with FastCGI, can be classified
- under three roles, 
-\emph on 
-Responder
-\emph default 
- (serving 
-\emph on 
-GET
-\emph default 
-, 
-\emph on 
-POST
-\emph default 
-, 
-\emph on 
-PUT
-\emph default 
-), 
-\emph on 
-Authorizer
-\emph default 
- (allowing or not access to a particular resource), and 
-\emph on 
-Filter
-\emph default 
- (allowing to transparently filter/process files).
-\layout Subsection
-
-Stateless commands
-\layout Standard
-
-These commands are always available independently of the current connection
- state.
-\layout Subsubsection
-
-ping
-\layout Itemize
-
-Request:
-\layout LyX-Code
-
-({cmd:
-\begin_inset Quotes erd
-\end_inset 
-
-ping
-\begin_inset Quotes erd
-\end_inset 
-
-})
-\layout Itemize
-
-Response:
-\layout LyX-Code
-
-({result:true, msg:
-\begin_inset Quotes erd
-\end_inset 
-
-pong
-\begin_inset Quotes erd
-\end_inset 
-
-})
-\layout Standard
-
-The main purpose of this command is to either verify if the connection still
- works properly, and/or to prevent the connection from being closed by js-appser
-v for inactivity timeout.
- Oftentimes the HTTPd will simply let the connection timeout automatically,
- which allows to free processes serving very idle sessions to serve more
- busy sessions.
-\layout Subsubsection
-
-
-\begin_inset LatexCommand \label{sub:quit}
-
-\end_inset 
-
-quit
-\layout Itemize
-
-Request:
-\layout LyX-Code
-
-({cmd:
-\begin_inset Quotes erd
-\end_inset 
-
-quit
-\begin_inset Quotes erd
-\end_inset 
-
-})
-\layout Itemize
-
-Response:
-\layout LyX-Code
-
-({result:true, msg:
-\begin_inset Quotes erd
-\end_inset 
-
-<message>
-\begin_inset Quotes erd
-\end_inset 
-
-})
-\layout Standard
-
-This command may be issued to immediately interrupt the connection at any
- time.
- If currently serving a SID, the session-specific data will be saved so
- that the session may be resumed.
-\layout Subsection
-
-The authentication state
-\layout Standard
-
-Every httpd->js-appserv connection starts in the greeting state.
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsection
-
-The SID management state
-\layout Standard
-
-After successful authentication, the HTTPd can request to resume a previous
- valid SID, or request that a new SID be created.
- It is also possible to verify for validity of a SID and then request a
- new one if the requested one did not exist, in which case the newly created
- SID should be sent again as session cookie to the user by the HTTPd.
-\layout Standard
-
-Care is made so that once activated on a connection, no other connection
- can activate the same SID, among other processes of the same js-appserv
- or between multiple local or remote ones.
- For this reason, SIDs are often stored into a common database (postgresql
- in the case of the reference implementation).
-\layout Standard
-
-However, if it is known that no conflict can occur (only a single js-appserv
- being run for instance, and that shared memory allows the various connections
- to share an in-memory hash table), an implementation could potentially
- use an in-memory system instead of depending on an RDBMS.
-\layout Standard
-
-This state begins with the message:
-\layout LyX-Code
-
-({result:true, msg:"Ready"})
-\layout Subsubsection
-
-sid_load
-\layout Itemize
-
-Request:
-\layout LyX-Code
-
-({cmd:
-\begin_inset Quotes erd
-\end_inset 
-
-sid_load
-\begin_inset Quotes erd
-\end_inset 
-
-, sid:
-\begin_inset Quotes erd
-\end_inset 
-
-<sid>
-\begin_inset Quotes erd
-\end_inset 
-
-})
-\layout Itemize
-
-Response:
-\layout LyX-Code
-
-({result:<boolean>, msg:
-\begin_inset Quotes erd
-\end_inset 
-
-<string>
-\begin_inset Quotes erd
-\end_inset 
-
-})
-\layout Standard
-
-Request to resume serving a specific session.
- This occurs after unexpected connection loss between the HTTPd and the
- js-appserv application, or after disconnection due to request inactivity
- timeout for the SID, where the closing phase saved persistent state information
- for it.
-\layout Standard
-
-If successful, this request causes the persistent data to be loaded back
- and the specified SID to become the active one for this connection.
- This request can only succeed if not currently serving a SID.
-\layout Standard
-
-On error, 
-\emph on 
-result
-\emph default 
- will be 
-\emph on 
-false
-\emph default 
- in the response, but the connection is left open for the HTTPd to optionally
- request creation of a new SID with the 
-\emph on 
-sid_create
-\emph default 
- (
-\begin_inset LatexCommand \ref{sub:sid_create}
-
-\end_inset 
-
-) command, although it may also issue the 
-\emph on 
-quit
-\emph default 
- (
-\begin_inset LatexCommand \ref{sub:quit}
-
-\end_inset 
-
-) command.
-\layout Subsubsection
-
-
-\begin_inset LatexCommand \label{sub:sid_create}
-
-\end_inset 
-
-sid_create
-\layout Itemize
-
-Request:
-\layout LyX-Code
-
-({cmd:
-\begin_inset Quotes erd
-\end_inset 
-
-sid_create
-\begin_inset Quotes erd
-\end_inset 
-
-})
-\layout Itemize
-
-Response:
-\layout LyX-Code
-
-{{result:<boolean>, msg:
-\begin_inset Quotes erd
-\end_inset 
-
-<string>
-\begin_inset Quotes erd
-\end_inset 
-
-[, sid:
-\begin_inset Quotes erd
-\end_inset 
-
-<sid>
-\begin_inset Quotes erd
-\end_inset 
-
-]})
-\layout Standard
-
-Requests that a new session be created.
- This is only possible if not currently serving a SID.
- When successful, the SID is returned and becomes the currently active SID
- being served by this connection.
-\layout Standard
-
-On error, 
-\emph on 
-result
-\emph default 
- is 
-\emph on 
-false
-\emph default 
- but the connection is left open.
- Failure here consists of an abnormal application error.
-\layout Subsubsection
-
-sid_destroy
-\layout Itemize
-
-Request:
-\layout LyX-Code
-
-({cmd:
-\begin_inset Quotes erd
-\end_inset 
-
-sid_destroy
-\begin_inset Quotes erd
-\end_inset 
-
-, sid:
-\begin_inset Quotes erd
-\end_inset 
-
-<sid>
-\begin_inset Quotes erd
-\end_inset 
-
-})
-\layout Itemize
-
-Response:
-\layout LyX-Code
-
-({result:<boolean>, msg:
-\begin_inset Quotes erd
-\end_inset 
-
-<string>
-\begin_inset Quotes erd
-\end_inset 
-
-})
-\layout Standard
-
-Requests that the currently being served session be destroyed.
- This is only possible if currently serving that particular SID.
- In general, SID expiration or the application will decide when to destroy
- the SID.
- This however is provided for convenience where the request could be initiated
- via the HTTPd.
- The connection is immediately closed after the SID is destroyed.
-\layout Subsection
-
-
-\begin_inset LatexCommand \label{sub:The-request-server}
-
-\end_inset 
-
-The request server state
-\layout Standard
-
-In this state the application can serve various requests for a specific
- SID until it expires or a request inactivity timeout occurs, causing a
- switch to 
-\emph on 
-The Closing State
-\emph default 
- (
-\begin_inset LatexCommand \ref{sub:The-closing-state}
-
-\end_inset 
-
-).
- These requests are only possible if currently serving a valid, unexpired
- SID.
- Multiple such requests are processed over the same persistent connection.
-\layout Subsubsection
-
-responder_get
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsubsection
-
-responder_post
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsubsection
-
-responder_put
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsubsection
-
-authorizer_*
-\layout Standard
-
-
-\emph on 
-XXX
-\layout Subsubsection
-
-filter_*
-\layout Standard
-
-
-\emph on 
-XXX Might not need SID?
-\layout Subsection
-
-
-\begin_inset LatexCommand \label{sub:The-closing-state}
-
-\end_inset 
-
-The closing state
-\layout Standard
-
-If the SID is not yet to be discarded, the application saves any persistent
- data for the SID before closing, so that resuming requests for it under
- a future connection be possible.
- The connection is then closed.
- This state information includes the 
-\emph on 
-DATA
-\emph default 
- object which is automatically hanled, as well as optional application specific
- data which might need saving (the application can provide a function to
- be called at this effect).
-\layout Section
-
-The Web Application Framework
-\layout Standard
-
-
-\emph on 
-XXX
-\the_end
diff --git a/mmsoftware/js/js-appserv/src/GNUmakefile b/mmsoftware/js/js-appserv/src/GNUmakefile
deleted file mode 100644 (file)
index bcc6a0f..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-# $Id: GNUmakefile,v 1.5 2006/10/28 22:02:51 mmondor Exp $
-
-CFLAGS += -Wall -DDEBUG
-
-JS_CFLAGS := $(shell spidermonkey-config -dc)
-JS_LDFLAGS := $(shell spidermonkey-config -dl)
-
-PG_CFLAGS := $(shell pg_config --cppflags)
-PG_CFLAGS += -I$(shell pg_config --includedir)
-PG_LDFLAGS := $(shell pg_config --ldflags)
-PG_LDFLAGS += -lpq
-
-GD_CFLAGS := $(shell gdlib-config --cflags)
-GD_LDFLAGS := $(shell gdlib-config --ldflags --libs)
-GD_LDFLAGS += -lgd
-
-
-MMOBJS := $(addprefix ../../../mmlib/,mmpool.o mmlog.o mmreadcfg.o \
-       mmstring.o mmhash.o mmalarm.o mmheap.o mmlimitrate.o mmserver2.o)
-JSOBJS := $(addprefix ../../classes/,js_gcroot.o js_errno.o js_fd.o js_file.o \
-       js_pgsql.o js_dir.o js_gd.o js_syslog.o)
-
-
-CFLAGS += $(JS_CFLAGS) $(PG_CFLAGS) $(GD_CFLAGS) -I. -I../../../mmlib \
-       -I../../classes
-LDFLAGS += $(JS_LDFLAGS) $(PG_LDFLAGS) $(GD_LDFLAGS)
-
-OBJ := js-appserv.o
-
-
-all: js-appserv
-
-%.o: %.c
-       cc -c $(CFLAGS) -o $@ $<
-
-js-appserv: $(OBJ) $(MMOBJS) $(JSOBJS)
-       cc -o $@ $(OBJ) $(LDFLAGS) -lc $(MMOBJS) $(JSOBJS)
-
-install: all
-       install -cs -o 0 -g 0 -m 500 js-appserv /usr/local/sbin
-       install -c -o 0 -g 0 -m 444 js-appserv.conf.5 /usr/local/man/man5
-       install -c -o 0 -g 0 -m 444 js-appserv.8 /usr/local/man/man8
-
-clean:
-       rm -f js-appserv $(OBJ) $(MMOBJS) $(JSOBJS)
diff --git a/mmsoftware/js/js-appserv/src/js-appserv.8 b/mmsoftware/js/js-appserv/src/js-appserv.8
deleted file mode 100644 (file)
index 844f954..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-.\" $Id: js-appserv.8,v 1.1 2006/08/20 06:59:00 mmondor Exp $
-.\"
-.\" Copyright (C) 2006, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\" 5. Redistribution of source code may not be released under the terms of
-.\"    any GNU Public License derivate.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd June 24, 2006
-.Dt JS-CGID 8
-.Os mmsoftware
-.Sh NAME
-.Nm js-appserv
-.Nd
-.Xr inetd 8
-alternative for better security
-.Sh SYNOPSIS
-.Nm js-appserv Op Ar config_file
-.Sh DESCRIPTION
-.Nm
-is a useful replacement for
-.Xr inetd 8
-when security is a concern. It only allows to serve one service per running
-instance, but a different configuration file can be provided for each service
-to run several ones as required. It supports connection number and rate limits
-on a global and per-address basis,
-.Xr chroot 2
-and
-.Xr setrlimit 2 . It will only
-.Xr bind 2
-to specified addresses/interfaces to listen for connections.
-It also ensures to drop privileges definitely before starting operation, using
-.Xr setgid 2 ,
-.Xr setuid 2
-and
-.Xr setgroups 2 .
-.Pp
-Further, it comports a safe
-.Xr execve 2
-wrapper which ensures to not pass unexpected arguments or environmental
-variables, as well as to only execute ELF binaries which are owned by the
-superuser and non-writable. No globbing whatsoever is performed by it,
-and it only allows an absolute path to be provided to the application to
-launch. It will not allow execution of files with the setuid or setgid
-bits set.
-.Pp
-All connections are logged via the specified facility using
-.Xr syslog 3 ,
-as well as the exit code of the application when closing the connection with
-the client. Any security issue encoutered by the
-.Xr execve 2
-wrapper is also logged.
-.Pp
-It's default configuration makes it harmless but useless. See the
-.Xr js-appserv.conf 5
-manual page for configuration file description.
-.Pp
-A good usage for
-.Xr js-appserv 8
-is for instance to run a CVS pserver in safe conditions. It then can be
-restrited to the specified root directory, and access the files with read-only
-access under an unprivileged user. If used for this purpose, also look at
-the
-.Xr mmanoncvs 8
-manual page.
-.Pp
-Another interesting feature is being able to specify if the currently running
-clients should be interrupted or not if the
-.Nm
-server is to be stopped or restarted. In the case of a CVS checkout for
-instance, if
-.Nm KILL_CHILDREN
-configuration option is FALSE, the operation will continue until it finishes
-normally, even in the event of a server configuration change or restart.
-.Pp
-For additional security, only the superuser is allowed to launch
-.Nm ,
-unless compiled with the
-.Nm -DNODROPPRIVS
-option, in which case it could be used by a nonprivileged user to bind
-a service to a high port, and server refuse to be launched by root.
-Other users attempting to launch the service will cause a line to be logged,
-telling which user ID attempted the launch.
-.Pp
-When launched successfully, a status line is logged telling under which 
-user ID it runs, which port it listens to and on which addresses/interfaces,
-as well as the configuration file location and service command.
-.Pp
-Note that this system redirects the stderr stream (filedescriptor 2) of
-the command launched to serve the clients to the "/dev/null" device, so that
-errors output from it be not disclosed to the remote user.
-.Pp
-Another optional interesting feature which it offers is the possibility
-to use advisory locking on a special control file to synchronize the service
-with another program. The lock is acquired in exclusive mode by
-.Nm
-when at least one connection exists being served. It is released when no
-more connections remain. This way, another program can rely on the fact that
-noone is using the service if it can obtain the lock. As long as the other
-application holds the lock, the service will refuse new connections. Normal
-service resumes immediately as the lock is released by the third party
-application. Of course, it is important to properly configure the permissions
-on that lock file, if the feature is enabled.
-.Pp
-Eventual support for bandwidth shaping/throttling and network inactivity
-timeout limits are planned. However, as those will require a redesign and
-rewrite of
-.Nm ,
-all we support for now is total maximum timeout for execution of the supplied
-service command. This is still better than
-.Xr inetd 8
-behavior, however.
-.Sh FILES
-.Bl -tag -width indent -offset indent
-.It Pa /usr/local/sbin/js-appserv
-The actual server binary
-.It Pa /usr/local/etc/js-appserv.conf
-The default configuration file to read
-.El
-.Sh AUTHOR
-.Nm
-was written by Matthew Mondor, and is
-Copyright (c) 2006, Matthew Mondor, All Rights Reserved.
-.Sh SEE ALSO
-.Xr js-appserv.conf 5 ,
-.Xr bind 2 ,
-.Xr chroot 2 ,
-.Xr setrlimit 2 ,
-.Xr setuid 2 ,
-.Xr setgid 2 ,
-.Xr setgroups 2 ,
-.Xr mmanoncvs 8 ,
-.Xr inetd 8 .
-.Sh BUGS
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/js/js-appserv/src/js-appserv.c b/mmsoftware/js/js-appserv/src/js-appserv.c
deleted file mode 100644 (file)
index c9e2ad0..0000000
+++ /dev/null
@@ -1,1075 +0,0 @@
-/* $Id: js-appserv.c,v 1.6 2006/10/28 22:02:51 mmondor Exp $ */
-
-/*
- * Copyright (C) 2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * TODO:
- * - Create the request structure object only once per request for performance
- * - Support option to allow to send the stderr output of launched processes
- *   to a file for debugging. This however requires support in mmserver2(3)
- *   for this.  This would only be for debugging, especially because of the
- *   fact that multiple processes could attempt to append at the end of the
- *   same file at once, concurrently. We can't really use a lock either, since
- *   we won't be controlling the output, unless we used a popen(3)-like
- *   system.
- * - Provide an enumeration for the reject handler reason parameter.
- * - Provide a few utility functions to the application, such as context
- *   creation and script execution, setting up timers, etc.
- * - Possibly let the application specify a setsockopt function.
- * - Perhaps create the JS contexts in the children processes between
- *   every connection in order to avoid any possible memory leaks.
- *   This of course would have a performance impact.  Interestingly, it is
- *   possible to not be necessary because of the GC, and moreover because
- *   we can recycle a process after serving a number of requests.
- */
-
-
-#include <sys/types.h>
-#include <sys/resource.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>            /* strerror(3) */
-#include <syslog.h>
-#include <unistd.h>
-
-#include <jsapi.h>
-
-#include <mmtypes.h>
-#include <mmreadcfg.h>
-#include <mmstring.h>
-#include <mmserver2.h>
-
-#include <js_gcroot.h>
-#include <js_syslog.h>
-#include <js_errno.h>
-#include <js_fd.h>
-#include <js_file.h>
-#include <js_pgsql.h>
-#include <js_dir.h>
-#include <js_gd.h>
-
-
-
-/* DEFINITIONS */
-
-struct config {
-       char SCRIPT_PATH[256], PROCTITLE[256], SYSLOG_FACILITY[32],
-           PID_PATH[256], LOCK_PATH[256], SHLOCKS_PATH[256], CHROOT_DIR[256],
-           USER[32], GROUPS[64], LISTEN_TO[256];
-       long CHILDREN_INITIAL, CHILDREN_MINSPARE, CHILDREN_MAXSPARE,
-           CHILDREN_MAXIMUM, CHILDREN_MAXIMUM_REQUESTS,
-           CHILDREN_AVERAGE_SECONDS, LISTEN_BACKLOG,
-           ADDRESS_CACHE_SIZE, ADDRESS_CACHE_RATE_LIMIT,
-           ADDRESS_CACHE_RATE_PERIOD, ADDRESS_CACHE_CONCURRENCY_LIMIT,
-           LIMIT_CORE, LIMIT_CPU, LIMIT_DATA, LIMIT_FSIZE, LIMIT_MEMLOCK,
-           LIMIT_NOFILE, LIMIT_NPROC, LIMIT_RSS, LIMIT_STACK;
-       bool USING_EXECVE, DROP_PRIVILEGES, EXIT_KILL_CHILDREN,
-           CHILDREN_SETSID, ADDRESS_RESOLVE, ADDRESS_RATE_LIMITS,
-           ADDRESS_CONCURRENCY_LIMITS, RLIMITS, SIGHUP_INTERRUPT_CHILDREN,
-           JS_GC_SIZE, JS_STACK_SIZE;
-};
-
-
-
-/* PROTOTYPES */
-
-int                    main(int, char **);
-
-static int             setsockopts(int);
-static int             config_read(const char *, uid_t *, gid_t **, int *);
-static int             lock_check(const char *);
-static int             listen_to(const char *);
-static int             rlimit_security(void);
-static JSBool          branch_callback(JSContext *, JSScript *);
-static void            context_error_reporter(JSContext *, const char *,
-                           JSErrorReport *);
-static JSContext       *context_create(JSRuntime *, size_t, JSObject **);
-static int             script_reload(const char *);
-static int             parent_init_hook(void);
-static void            parent_exit_hook(void);
-static void            parent_sighup_hook(void);
-static int             child_init_hook(void);
-static void            child_exit_hook(void);
-static void            child_sigalrm_hook(void);
-static JSObject                *server_request_object(struct server_request *);
-static void            server_request_object_destroy(void);
-static void            request_handler(struct server_request *);
-static void            reject_handler(struct server_request *, int);
-static void            request_close_hook(struct server_request *);
-static void            request_interrupt_hook(struct server_request *);
-
-
-
-/* GLOBALS */
-
-static struct config   CONF;
-static char            daemon_title[64];
-
-/* For mmreadcfg() */
-static carg_t  cargs[] = {
-       {CAT_STR, CAF_NONE, 1, 255, "SCRIPT_PATH", CONF.SCRIPT_PATH},
-       {CAT_STR, CAF_NONE, 1, 63, "PROCTITLE", CONF.PROCTITLE},
-       {CAT_STR, CAF_NONE, 1, 31, "SYSLOG_FACILITY", CONF.SYSLOG_FACILITY},
-       {CAT_STR, CAF_NONE, 1, 255, "PID_PATH", CONF.PID_PATH},
-       {CAT_STR, CAF_NONE, 1, 255, "LOCK_PATH", CONF.LOCK_PATH},
-       {CAT_STR, CAF_NONE, 1, 255, "SHLOCKS_PATH", CONF.SHLOCKS_PATH},
-       {CAT_STR, CAF_NONE, 1, 255, "CHROOT_DIR", CONF.CHROOT_DIR},
-       {CAT_STR, CAF_NONE, 1, 31, "USER", CONF.USER},
-       {CAT_STR, CAF_NONE, 1, 63, "GROUPS", CONF.GROUPS},
-       {CAT_STR, CAF_NONE, 1, 255, "LISTEN_TO", CONF.LISTEN_TO},
-       {CAT_VAL, CAF_NONE, 1, 1024, "CHILDREN_INITIAL",
-               &CONF.CHILDREN_INITIAL},
-       {CAT_VAL, CAF_NONE, 1, 1024, "CHILDREN_MINSPARE",
-               &CONF.CHILDREN_MINSPARE},
-       {CAT_VAL, CAF_NONE, 1, 1024, "CHILDREN_MAXSPARE",
-               &CONF.CHILDREN_MAXSPARE},
-       {CAT_VAL, CAF_NONE, 1, 1024, "CHILDREN_MAXIMUM",
-               &CONF.CHILDREN_MAXIMUM},
-       {CAT_VAL, CAF_NONE, 1, 1024, "CHILDREN_MAXIMUM_REQUESTS",
-               &CONF.CHILDREN_MAXIMUM_REQUESTS},
-       {CAT_VAL, CAF_NONE, 1, 1024, "CHILDREN_AVERAGE_SECONDS",
-               &CONF.CHILDREN_AVERAGE_SECONDS},
-       {CAT_VAL, CAF_NONE, 0, 99999, "LISTEN_BACKLOG", &CONF.LISTEN_BACKLOG},
-       {CAT_VAL, CAF_NONE, 0, 4096, "ADDRESS_CACHE_SIZE",
-               &CONF.ADDRESS_CACHE_SIZE},
-       {CAT_VAL, CAF_NONE, 0, 4096, "ADDRESS_CACHE_RATE_LIMIT",
-               &CONF.ADDRESS_CACHE_RATE_LIMIT},
-       {CAT_VAL, CAF_NONE, 0, 1800, "ADDRESS_CACHE_RATE_PERIOD",
-               &CONF.ADDRESS_CACHE_RATE_PERIOD},
-       {CAT_VAL, CAF_NONE, 0, 1024, "ADDRESS_CACHE_CONCURRENCY_LIMIT",
-               &CONF.ADDRESS_CACHE_CONCURRENCY_LIMIT},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_CORE", &CONF.LIMIT_CORE},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_CPU", &CONF.LIMIT_CPU},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_DATA", &CONF.LIMIT_DATA},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_FSIZE", &CONF.LIMIT_FSIZE},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_MEMLOCK", &CONF.LIMIT_MEMLOCK},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_NOFILE", &CONF.LIMIT_NOFILE},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_NPROC", &CONF.LIMIT_NPROC},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_RSS", &CONF.LIMIT_RSS},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_STACK", &CONF.LIMIT_STACK},
-        {CAT_VAL, CAF_NONE, 0, 0, "JS_GC_SIZE", &CONF.JS_GC_SIZE},
-        {CAT_VAL, CAF_NONE, 0, 0, "JS_STACK_SIZE", &CONF.JS_STACK_SIZE},
-       {CAT_BOOL, CAF_NONE, 0, 0, "USING_EXECVE", &CONF.USING_EXECVE},
-       {CAT_BOOL, CAF_NONE, 0, 0, "DROP_PRIVILEGES", &CONF.DROP_PRIVILEGES},
-       {CAT_BOOL, CAF_NONE, 0, 0, "EXIT_KILL_CHILDREN",
-               &CONF.EXIT_KILL_CHILDREN},
-       {CAT_BOOL, CAF_NONE, 0, 0, "CHILDREN_SETSID", &CONF.CHILDREN_SETSID},
-       {CAT_BOOL, CAF_NONE, 0, 0, "ADDRESS_RESOLVE", &CONF.ADDRESS_RESOLVE},
-       {CAT_BOOL, CAF_NONE, 0, 0, "ADDRESS_RATE_LIMITS",
-               &CONF.ADDRESS_RATE_LIMITS},
-       {CAT_BOOL, CAF_NONE, 0, 0, "ADDRESS_CONCURRENCY_LIMITS",
-               &CONF.ADDRESS_CONCURRENCY_LIMITS},
-       {CAT_BOOL, CAF_NONE, 0, 0, "RLIMITS", &CONF.RLIMITS},
-       {CAT_BOOL, CAF_NONE, 0, 0, "SIGHUP_INTERRUPT_CHILDREN",
-               &CONF.SIGHUP_INTERRUPT_CHILDREN},
-       {CAT_END, CAF_NONE, 0, 0, NULL, NULL}
-};
-static cmap_t  cmap[] = {
-       {"LOG_AUTH", LOG_AUTH},
-       {"LOG_AUTHPRIV", LOG_AUTHPRIV},
-       {"LOG_CRON", LOG_CRON},
-       {"LOG_DAEMON", LOG_DAEMON},
-       {"LOG_FTP", LOG_FTP},
-       {"LOG_LPR", LOG_LPR},
-       {"LOG_MAIL", LOG_MAIL},
-       {"LOG_NEWS", LOG_NEWS},
-       {"LOG_SYSLOG", LOG_SYSLOG},
-       {"LOG_USER", LOG_USER},
-       {"LOG_UUCP", LOG_UUCP},
-       {NULL, 0}
-};
-
-static JSClass class_global = {
-       "global", 0, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
-       JS_FinalizeStub
-};
-
-/*
- * The JS runtime and context is global, inherited from the parent to the
- * children processes.
- */
-JSRuntime      *p_rt = NULL;
-JSBool         p_map = JS_FALSE;
-JSContext      *p_ctx = NULL;
-JSObject       *p_obj = NULL;
-JSScript       *p_script = NULL;
-jsval          p_robj;
-
-/*
- * And these are used by the children processes
- */
-JSContext      *c_ctx;
-
-
-
-/* TEXT */
-
-int
-main(int argc, char **argv)
-{
-       struct server_config    c;
-       uid_t                   uid;
-       gid_t                   *gids;
-       int                     ngids, ch;
-       char                    *conf_file = "/usr/local/etc/js-appserv.conf";
-
-       /*
-        * Make sure that only the superuser may launch this daemon
-        */
-#ifdef SUPERUSER_ONLY
-       if (getuid() != 0) {
-               (void) fprintf(stderr,
-                   "Only can be started by the superuser\n");
-               syslog(LOG_NOTICE,
-                   "User %d attempted to launch js-appserv with '%s'",
-                   getuid(), conf_file);
-               exit(EXIT_FAILURE);
-       }
-#endif
-
-       /*
-        * Parse command line arguments
-        */
-       while ((ch = getopt(argc, argv, "f:")) != -1) {
-               switch (ch) {
-               case 'f':
-                       conf_file = optarg;
-                       break;
-               case '?':
-                       /* FALLTHROUGH */
-               default:
-                       (void) fprintf(stderr,
-                           "usage: js-appserv [-f <configfile>]\n");
-                       exit(EXIT_FAILURE);
-               }
-       }
-       argc -= optind;
-       argv += optind;
-
-       /*
-        * Things we must do before calling chroot(2)
-        */
-
-       /* Read config file. This also calls openlog(3) for us */
-       if (config_read(conf_file, &uid, &gids, &ngids) == -1) {
-               (void) fprintf(stderr, "Error reading configuration file."
-                   " Verify syslog for more details.\n");
-               exit(EXIT_FAILURE);
-       }
-
-       /* Make sure that we're not already running */
-       if (lock_check(CONF.LOCK_PATH) == -1) {
-               (void) fprintf(stderr, "Already running!? - %s\n",
-                   strerror(errno));
-               syslog(LOG_NOTICE, "Already running!? - %s", strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * Chroot if wanted. Note that server_start() will chdir(2), but since
-        * we can setup any files we may need, we chdir(2) here as well.
-        */
-       if (*CONF.CHROOT_DIR != '\0') {
-               if (chroot(CONF.CHROOT_DIR) == -1) {
-                       syslog(LOG_NOTICE, "chroot(%s) - %s", CONF.CHROOT_DIR,
-                           strerror(errno));
-                       exit(EXIT_FAILURE);
-               }
-               (void) chdir("/");
-       }
-
-       /*
-        * Bind network server ports.
-        */
-       server_init();
-       if (listen_to(CONF.LISTEN_TO) == -1)
-               exit(EXIT_FAILURE);
-
-       /*
-        * Finally drop privileges.
-        */
-       if ((CONF.DROP_PRIVILEGES && getuid() == 0) &&
-           !mmdropprivs(uid, gids, ngids)) {
-               syslog(LOG_NOTICE, "Error dropping privileges - %s",
-                   strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * Initialize and start server. New user must be able to create lock
-        * files as necessary where specified in SHLOCKS_PATH configuration
-        * directive.
-        */
-       (void) mm_memclr(&c, sizeof(struct server_config));
-       (void) mm_strcpy(c.locks_path, CONF.SHLOCKS_PATH);
-       *c.locks_user = '\0';
-       *c.locks_group = '\0';
-       c.locks_mode = 0600;
-       (void) mm_strcpy(c.null_path, "/dev/null");
-       (void) mm_strcpy(c.pid_path, CONF.PID_PATH);
-       (void) mm_strncpy(c.proc_title, CONF.PROCTITLE, 31);
-       c.children_initial = CONF.CHILDREN_INITIAL;
-       c.children_minspare = CONF.CHILDREN_MINSPARE;
-       c.children_maxspare = CONF.CHILDREN_MAXSPARE;
-       c.children_maximum = CONF.CHILDREN_MAXIMUM;
-       c.children_average_seconds = CONF.CHILDREN_AVERAGE_SECONDS;
-       c.children_maxrequests = CONF.CHILDREN_MAXIMUM_REQUESTS;
-       c.serialization_lock = TRUE;
-       c.exit_interrupt_requests = CONF.EXIT_KILL_CHILDREN;
-       c.children_setsid = CONF.CHILDREN_SETSID;
-       c.using_execve = CONF.USING_EXECVE;
-       c.parent_init_hook = parent_init_hook;
-       c.parent_exit_hook = parent_exit_hook;
-       c.parent_sighup_hook = parent_sighup_hook;
-       c.parent_timer_hook = NULL;
-       c.parent_timer_seconds = 0;
-       c.child_init_hook = child_init_hook;
-       c.child_exit_hook = child_exit_hook;
-       c.child_sigalrm_hook = child_sigalrm_hook;
-       if (server_start(&c) == -1)
-               exit(EXIT_FAILURE);
-
-       /* NOTREACHED */
-       exit(EXIT_SUCCESS);
-}
-
-static int
-config_read(const char *file, uid_t *uid, gid_t **gids, int *ngids)
-{
-       cres_t  cres;
-       long    facility;
-
-       /*
-        * Set configuration defaults
-        */
-       (void) mm_strcpy(CONF.SCRIPT_PATH, "/app/main.js");
-       *CONF.PROCTITLE = '\0';
-       (void) mm_strcpy(CONF.SYSLOG_FACILITY, "LOG_DAEMON");
-       (void) mm_strcpy(CONF.PID_PATH, "/var/run/js-appserv.pid");
-       (void) mm_strcpy(CONF.LOCK_PATH, "/var/run/js-appserv-lock");
-       (void) mm_strcpy(CONF.SHLOCKS_PATH, "/var/run/js-appserv-lock");
-       *CONF.CHROOT_DIR = '\0';
-       (void) mm_strcpy(CONF.USER, "js-appserv");
-       (void) mm_strcpy(CONF.GROUPS, "js-appserv");
-       (void) mm_strcpy(CONF.LISTEN_TO, "127.0.0.1:2323");
-       CONF.CHILDREN_INITIAL = 5;
-       CONF.CHILDREN_MINSPARE = 5;
-       CONF.CHILDREN_MAXSPARE = 10;
-       CONF.CHILDREN_MAXIMUM = 64;
-       CONF.CHILDREN_MAXIMUM_REQUESTS = 5000;
-       CONF.CHILDREN_AVERAGE_SECONDS = 300;
-       CONF.LISTEN_BACKLOG = 256;
-       CONF.USING_EXECVE = FALSE;
-       CONF.DROP_PRIVILEGES = TRUE;
-       CONF.EXIT_KILL_CHILDREN = TRUE;
-       CONF.CHILDREN_SETSID = FALSE;
-       CONF.ADDRESS_RESOLVE = FALSE;
-       CONF.ADDRESS_RATE_LIMITS = FALSE;
-       CONF.ADDRESS_CONCURRENCY_LIMITS = FALSE;
-       CONF.ADDRESS_CACHE_SIZE = 0;
-       CONF.ADDRESS_CACHE_RATE_LIMIT = 0;
-       CONF.ADDRESS_CACHE_RATE_PERIOD = 0;
-       CONF.ADDRESS_CACHE_CONCURRENCY_LIMIT = 0;
-       CONF.RLIMITS = FALSE;
-       CONF.LIMIT_CORE = -1;
-       CONF.LIMIT_CPU = -1;
-       CONF.LIMIT_DATA = -1;
-       CONF.LIMIT_FSIZE = -1;
-       CONF.LIMIT_MEMLOCK = -1;
-       CONF.LIMIT_NOFILE = -1;
-       CONF.LIMIT_NPROC = -1;
-       CONF.LIMIT_RSS = -1;
-       CONF.LIMIT_STACK = -1;
-       CONF.JS_GC_SIZE = 1024;
-       CONF.JS_STACK_SIZE = 8;
-       CONF.SIGHUP_INTERRUPT_CHILDREN = FALSE;
-
-       /*
-        * Read and parse configuration file
-        */
-       if (!mmreadcfg(&cres, cargs, file)) {
-               syslog(LOG_NOTICE, "Cannot read configuration file '%s'",
-                   file);
-               return -1;
-       }
-
-       /*
-        * Setup syslog. First perform sanity checking on supplied syslog
-        * facility string.
-        */
-       if (!mmmapstring(cmap, CONF.SYSLOG_FACILITY, &facility)) {
-               syslog(LOG_NOTICE, "Invalid syslog facility '%s'",
-                   CONF.SYSLOG_FACILITY);
-               return -1;
-       }
-       if (*CONF.PROCTITLE != '\0')
-               (void) snprintf(daemon_title, 63, "js-appserv:%s",
-                   CONF.PROCTITLE);
-       else
-               (void) mm_strcpy(daemon_title, "js-appserv");
-       openlog(daemon_title, LOG_PID | LOG_NDELAY, facility);
-
-       /*
-        * Now do some sanity checking on supplied users and groups, we'll
-        * return those properly if they are valid.
-        */
-       if ((*uid = mmgetuid(CONF.USER)) == -1) {
-               syslog(LOG_NOTICE, "Unknown user '%s'", CONF.USER);
-               return -1;
-       }
-       if (!(*gids = mmgetgidarray(ngids, CONF.GROUPS))) {
-               syslog(LOG_NOTICE, "At least one unknown group in '%s'",
-                   CONF.GROUPS);
-               return -1;
-       }
-
-       /* Everything successful */
-       return 0;
-}
-
-/*
- * Function to verify if we are already running. Every configuration should
- * provide a lock file path to do this check.
- */
-static int
-lock_check(const char *file)
-{
-       int fd;
-
-       if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600)) != -1) {
-               if (flock(fd, LOCK_EX | LOCK_NB) == 0)
-                       return 0;
-               close(fd);
-       }
-
-       return -1;
-}
-
-/*
- * Set wanted setsockopt(2) on sockets. This function is called internally for
- * each socket we create using server_socket_bind().
- */
-static int
-setsockopts(int fd)
-{
-       struct linger   l;
-
-#define SETSOCKOPT(l, o)       do {                                    \
-       int     _o = 1;                                                 \
-       if ((setsockopt(fd, (l), (o), &_o, sizeof(int))) == -1)         \
-               return -1;                                              \
-} while (/* CONSTCOND */0)
-
-       SETSOCKOPT(SOL_SOCKET, SO_REUSEADDR);
-       SETSOCKOPT(SOL_SOCKET, SO_REUSEPORT);
-       SETSOCKOPT(SOL_SOCKET, SO_KEEPALIVE);
-
-#undef SETSOCKOPT
-
-       l.l_onoff = 0;
-       l.l_linger = 0;
-       if ((setsockopt(fd, SOL_SOCKET, SO_LINGER, &l,
-                       sizeof(struct linger))) == -1)
-               return -1;
-
-       /* XXX Add TCP_NODELAY */
-
-       return 0;
-}
-
-/*
- * Starts listening to all specified address:port pairs. Returns 0 on
- * success, or -1 on error, logging the error via syslog(3).
- */
-static int
-listen_to(const char *addresses)
-{
-       char    *string, *tstring;
-       char    *entries[32], *cols[3];
-       int     i, nentries, err;
-
-       string = tstring = NULL;
-       err = 0;
-
-       if ((string = _mm_strdup(addresses)) == NULL) {
-               syslog(LOG_NOTICE, "listen_to() - Out of memory error");
-               return -1;
-       }
-
-       if ((nentries = mm_straspl(entries, string, 31)) < 1) {
-               syslog(LOG_NOTICE, "No <address>:<port> specified in "
-                   "LISTEN_TO configuration directive");
-               err = -1;
-               goto end;
-       }
-
-       for (i = 0; i < nentries; i++) {
-               struct server_socket_config     sc;
-
-               tstring = _mm_strdup(entries[i]);
-               if (mm_strspl(cols, entries[i], 2, ':') != 2) {
-                       syslog(LOG_NOTICE,
-                           "[%s] not a valid <address>:<port> entry in "
-                           "LISTEN_TO configuration directive", tstring);
-                       err = -1;
-                       goto end;
-               }
-
-               (void) mm_memclr(&sc, sizeof(struct server_socket_config));
-               sc.family = (mm_strchr(cols[0], ':') != NULL ?
-                   AF_INET6 : AF_INET);
-               sc.type = SOCK_STREAM;
-               sc.port = (int)strtol(cols[1], NULL, 10);
-               sc.backlog = CONF.LISTEN_BACKLOG;
-               sc.create_stream = FALSE;
-               sc.address_resolve = CONF.ADDRESS_RESOLVE;
-               sc.address_rate_limits = CONF.ADDRESS_RATE_LIMITS;
-               sc.address_concurrency_limits =
-                   CONF.ADDRESS_CONCURRENCY_LIMITS;
-               sc.address_cache_size = CONF.ADDRESS_CACHE_SIZE;
-               sc.address_cache_rate_limit = CONF.ADDRESS_CACHE_RATE_LIMIT;
-               sc.address_cache_rate_period = CONF.ADDRESS_CACHE_RATE_PERIOD;
-               sc.address_cache_concurrency_limit =
-                   CONF.ADDRESS_CACHE_CONCURRENCY_LIMIT;
-               sc.packet_size = 0;
-               (void) mm_strcpy(sc.bind_address, cols[0]);
-               *sc.socket_user = '\0';
-               *sc.socket_group = '\0';
-               sc.socket_mode = 0;
-               sc.setsockopts = setsockopts;
-               sc.request_handler = request_handler;
-               sc.reject_handler = reject_handler;
-               sc.request_interrupt_hook = request_interrupt_hook;
-               sc.request_close_hook = request_close_hook;
-               sc.user_data = NULL;
-               if (server_socket_bind(&sc) == -1)
-                       syslog(LOG_NOTICE, "Error binding socket for [%s]",
-                           tstring);
-
-               free(tstring);
-               tstring = NULL;
-       }
-
-end:
-       if (string != NULL)
-               free(string);
-       if (tstring != NULL)
-               free(tstring);
-
-       return err;
-}
-
-static int
-rlimit_security(void)
-{
-       struct rlimit   rl;
-
-/*
- * Use some preprocessor magic to shorten and clean up repetitive code:
- */
-
-#define SETRLIMIT(restxt, resource, limit) do {                                \
-       if ((limit) != -1) {                                            \
-               rl.rlim_cur = rl.rlim_max = (rlim_t)(limit);            \
-               if (setrlimit((resource), &rl) == -1) {                 \
-                       syslog(LOG_NOTICE,                              \
-                           "* setrlimit(R%s, %ld) - (%s)",             \
-                           (restxt), (limit), strerror(errno));        \
-                       return -1;                                      \
-               }                                                       \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-#define SETRLIMIT2(n)  SETRLIMIT(#n, R##n, CONF.n)
-
-       SETRLIMIT2(LIMIT_CORE);
-       SETRLIMIT2(LIMIT_CPU);
-       SETRLIMIT2(LIMIT_DATA);
-       SETRLIMIT2(LIMIT_FSIZE);
-       SETRLIMIT2(LIMIT_MEMLOCK);
-       SETRLIMIT2(LIMIT_NOFILE);
-       SETRLIMIT2(LIMIT_NPROC);
-       SETRLIMIT2(LIMIT_RSS);
-       SETRLIMIT2(LIMIT_STACK);
-
-#undef SETRLIMIT2
-#undef SETRLIMIT
-
-       return 0;
-}
-
-static JSBool
-branch_callback(JSContext *ctx, JSScript *s)
-{
-       static int      count = 0;
-
-       if ((++count & 0x3fff) == 1)
-               JS_MaybeGC(ctx);
-
-       return JS_TRUE;
-}
-
-static void
-context_error_reporter(JSContext *cx, const char *msg, JSErrorReport *rep)
-{
-
-       syslog(LOG_NOTICE, "context_error_reporter() - %s : %s",
-           msg, rep->linebuf);
-}
-
-static JSContext *
-context_create(JSRuntime *rt, size_t stacksize, JSObject **obj)
-{
-       JSContext       *ctx;
-
-       if ((ctx = JS_NewContext(rt, stacksize)) == NULL) {
-               syslog(LOG_NOTICE, "context_create() - JS_NewContext()");
-               goto err;
-       }
-       (void) JS_SetErrorReporter(ctx, context_error_reporter);
-       if ((*obj = JS_NewObject(ctx, &class_global, NULL, NULL)) == NULL) {
-               syslog(LOG_NOTICE, "context_create() - JS_NewObject()");
-               goto err;
-       }
-       if (!JS_InitStandardClasses(ctx, *obj)) {
-               syslog(LOG_NOTICE,
-                   "context_create() - JS_InitStandardClasses()");
-               goto err;
-       }
-
-       /* Wanted custom classes */
-       if (!js_InitGCRoot(ctx)) {
-               syslog(LOG_NOTICE, "context_create() - js_InitGCRoot()");
-               goto err;
-       }
-       if (!js_InitSyslogClass(ctx, *obj)) {
-               syslog(LOG_NOTICE, "context_create() - js_InitSyslogClass()");
-               goto err;
-       }
-       if (!js_InitErrnoClass(ctx, *obj)) {
-               syslog(LOG_NOTICE, "context_create() - js_InitErrnoClass()");
-               goto err;
-       }
-       if (!js_InitFDClass(ctx, *obj)) {
-               syslog(LOG_NOTICE, "context_create() - js_InitFDClass()");
-               goto err;
-       }
-       if (!js_InitFileClass(ctx, *obj)) {
-               syslog(LOG_NOTICE, "context_create() - js_InitFileClass()");
-               goto err;
-       }
-       if (!js_InitPGClass(ctx, *obj)) {
-               syslog(LOG_NOTICE, "context_create() - js_InitPGClass()");
-               goto err;
-       }
-       if (!js_InitDirClass(ctx, *obj)) {
-               syslog(LOG_NOTICE, "context_create() - js_InitDirClass()");
-               goto err;
-       }
-       if (!js_InitGDClass(ctx, *obj)) {
-               syslog(LOG_NOTICE, "context_create() - js_InitGDClass()");
-               goto err;
-       }
-
-       /* Set our GC handler callback */
-       (void) JS_SetBranchCallback(ctx, branch_callback);
-
-       return ctx;
-
-err:
-       if (ctx != NULL) {
-               js_DestroyGCRoot(ctx);
-               JS_DestroyContext(ctx);
-       }
-
-       return NULL;
-}
-
-/*
- * Attempt to load, preprocess and compile the supplied script.
- * This also sets up the runtime environment and the classes.
- * Occurs in the parent process, but before the children are started/recycled.
- * On failure, we return -1 and we leave the previously compiled script
- * as-is.  On success, any previously compiled script is freed and we
- * return 0.
- * If called with file == NULL, only frees any allocated script.
- */
-static int
-script_reload(const char *file)
-{
-       JSRuntime       *rt = NULL;
-       JSBool          map = JS_FALSE;
-       JSContext       *ctx = NULL;
-       JSObject        *obj, *robj;
-       JSScript        *script = NULL;
-       jsval           val;
-
-       if (file == NULL) {
-               if (p_script != NULL && p_ctx != NULL) {
-                       JS_DestroyScript(p_ctx, p_script);
-                       p_script = NULL;
-               }
-               if (p_ctx != NULL) {
-                       (void) JS_RemoveRoot(p_ctx, &p_robj);
-                       js_DestroyGCRoot(p_ctx);
-                       JS_DestroyContext(p_ctx);
-                       p_ctx = NULL;
-               }
-               if (p_map) {
-                       js_map_destroy();
-                       p_map = JS_FALSE;
-               }
-               if (p_rt != NULL) {
-                       JS_DestroyRuntime(p_rt);
-                       p_rt = NULL;
-               }
-
-               return 0;
-       }
-
-       if ((rt = JS_NewRuntime(CONF.JS_GC_SIZE * 1024)) == NULL) {
-               syslog(LOG_NOTICE, "script_reload() - JS_NewRuntime()");
-               goto err;
-       }
-       if (!(map = js_map_init())) {
-               syslog(LOG_NOTICE, "script_reload() - js_map_init()");
-               goto err;
-       }
-       if ((ctx = context_create(rt, CONF.JS_STACK_SIZE * 1024, &obj))
-           == NULL) {
-               syslog(LOG_NOTICE, "script_reload() - context_create()");
-               goto err;
-       }
-
-       if ((script = JS_CompileFile(ctx, obj, CONF.SCRIPT_PATH)) == NULL) {
-               syslog(LOG_NOTICE, "script_reload() - JS_CompileFile()");
-               goto err;
-       }
-       if (!JS_ExecuteScript(ctx, obj, script, &val)) {
-               syslog(LOG_NOTICE, "script_reload() - JS_ExecuteScript()");
-               goto err;
-       }
-
-       /*
-        * Create a rooted object which can be used to store arguments objects
-        * sent to called functions
-        */
-       if ((robj = JS_NewObject(ctx, NULL, NULL, NULL)) == NULL) {
-               syslog(LOG_NOTICE, "script_reload() - JS_NewObject()");
-               goto err;
-       }
-       p_robj = OBJECT_TO_JSVAL(robj);
-       if (!JS_AddRoot(ctx, &p_robj))
-               syslog(LOG_NOTICE, "script_reload() - JS_AddRoot()");
-
-       /* Trick to free previous values :) */
-       (void) script_reload(NULL);
-       p_obj = obj;
-       p_script = script;
-       p_ctx = ctx;
-       p_map = map;
-       p_rt = rt;
-
-       return 0;
-
-err:
-       if (script && ctx)
-               JS_DestroyScript(ctx, script);
-       if (ctx) {
-               js_DestroyGCRoot(ctx);
-               JS_DestroyContext(ctx);
-       }
-       if (map)
-               js_map_destroy();
-       if (rt)
-               JS_DestroyRuntime(rt);
-
-       syslog(LOG_NOTICE,
-           "script_reload() - Preserving previous script if any");
-
-       return -1;
-}
-
-static int
-parent_init_hook(void)
-{
-
-       return script_reload(CONF.SCRIPT_PATH);
-}
-
-static void
-parent_exit_hook(void)
-{
-
-       (void) script_reload(NULL);
-}
-
-static void
-parent_sighup_hook(void)
-{
-
-       syslog(LOG_NOTICE, "Received SIGHUP, reloading JS application");
-
-       if (script_reload(CONF.SCRIPT_PATH) == 0)
-               server_recycle(CONF.SIGHUP_INTERRUPT_CHILDREN);
-}
-
-static int
-child_init_hook(void)
-{
-       jsval   args, ret;
-
-       if (CONF.RLIMITS && rlimit_security() == -1)
-               return -1;
-
-       if (!JS_CallFunctionName(p_ctx, p_obj, "child_init_hook", 0, &args,
-           &ret)) {
-               syslog(LOG_NOTICE,
-                   "child_init_hook() - JS_CallFunctionName()");
-               return -1;
-       }
-
-       return 0;
-}
-
-static void
-child_exit_hook(void)
-{
-       jsval   args, ret;
-
-       if (!JS_CallFunctionName(p_ctx, p_obj, "child_exit_hook", 0, &args,
-           &ret))
-               syslog(LOG_NOTICE,
-                   "child_exit_hook() - JS_CallFunctionName()");
-}
-
-static void
-child_sigalrm_hook(void)
-{
-       jsval   args, ret;
-
-       if (!JS_CallFunctionName(p_ctx, p_obj, "child_sigalrm_hook", 0, &args,
-           &ret))
-               syslog(LOG_NOTICE,
-                   "child_sigalrm_hook() - JS_CallFunctionName()");
-}
-
-static JSObject        *
-server_request_object(struct server_request *r)
-{
-       JSObject        *o;
-
-       if ((o = JS_NewObject(p_ctx, NULL, NULL, NULL)) == NULL) {
-               syslog(LOG_NOTICE, "request_handler() - JS_NewObject()");
-               goto err;
-       }
-       /* Root object immediately */
-       if (!JS_DefineProperty(p_ctx, JSVAL_TO_OBJECT(p_robj), "args",
-           OBJECT_TO_JSVAL(o), NULL, NULL, JSPROP_ENUMERATE)) {
-               syslog(LOG_NOTICE, "request_handler() - Root");
-               goto err;
-       }
-
-       if (!JS_DefineProperty(p_ctx, o, "server_socket",
-           INT_TO_JSVAL(r->server_socket), NULL, NULL, JSPROP_ENUMERATE))
-               goto err2;
-       if (!JS_DefineProperty(p_ctx, o, "client_socket",
-           INT_TO_JSVAL(r->client_socket), NULL, NULL, JSPROP_ENUMERATE))
-               goto err2;
-       if (!JS_DefineProperty(p_ctx, o, "server_socket_type",
-           INT_TO_JSVAL(r->server_socket_type), NULL, NULL,
-           JSPROP_ENUMERATE))
-               goto err2;
-       if (!JS_DefineProperty(p_ctx, o, "server_socket_family",
-           INT_TO_JSVAL(r->server_socket_family), NULL, NULL,
-           JSPROP_ENUMERATE))
-               goto err2;
-       if (!JS_DefineProperty(p_ctx, o, "client_port",
-           INT_TO_JSVAL(r->client_port), NULL, NULL, JSPROP_ENUMERATE))
-               goto err2;
-       if (!JS_DefineProperty(p_ctx, o, "server_socket_port",
-           INT_TO_JSVAL(r->server_socket_port), NULL, NULL,
-           JSPROP_ENUMERATE))
-               goto err2;
-       if (!JS_DefineProperty(p_ctx, o, "server_socket_address_name",
-           STRING_TO_JSVAL(JS_NewStringCopyZ(p_ctx,
-           r->server_socket_address_name)), NULL, NULL, JSPROP_ENUMERATE))
-               goto err2;
-       if (!JS_DefineProperty(p_ctx, o, "client_address_name",
-           STRING_TO_JSVAL(JS_NewStringCopyZ(p_ctx, r->client_address_name)),
-           NULL, NULL, JSPROP_ENUMERATE))
-               goto err2;
-       if (!JS_DefineProperty(p_ctx, o, "client_address_hostname",
-           STRING_TO_JSVAL(JS_NewStringCopyZ(p_ctx,
-           r->client_address_hostname)), NULL, NULL, JSPROP_ENUMERATE))
-               goto err2;
-       {
-               jsval   val;
-
-               /* uint32_t so might require a double JS object */
-               if (!JS_NewDoubleValue(p_ctx,
-                   (jsdouble)r->client_address_concurrency, &val)) {
-                       syslog(LOG_NOTICE,
-                           "server_request_object() - JS_NewDoubleValue()");
-                       goto err;
-               }
-               if (!JS_DefineProperty(p_ctx, o, "client_address_concurrency",
-                       val, NULL, NULL, JSPROP_ENUMERATE))
-                       goto err2;
-       }
-       if (r->packet_data != NULL) {
-               if (!JS_DefineProperty(p_ctx, o, "packet_data",
-                   STRING_TO_JSVAL(JS_NewStringCopyN(p_ctx, r->packet_data,
-                   r->packet_size)), NULL, NULL, JSPROP_ENUMERATE))
-               goto err2;
-       }
-
-       return o;
-
-err2:
-       syslog(LOG_NOTICE, "server_request_object() - JS_DefineProperty()");
-err:
-       return NULL;
-}
-
-static void
-server_request_object_destroy(void)
-{
-
-       (void) JS_DeleteProperty(p_ctx, JSVAL_TO_OBJECT(p_robj), "args");
-}
-
-static void
-request_handler(struct server_request *r)
-{
-       JSObject        *o;
-       jsval           args[1], ret;
-
-       syslog(LOG_NOTICE, "Request from [%s]", r->client_address_name);
-
-       if ((o = server_request_object(r)) == NULL) {
-               syslog(LOG_NOTICE,
-                   "request_handler() - server_request_object()");
-               goto err;
-       }
-       *args = OBJECT_TO_JSVAL(o);
-
-       if (!JS_CallFunctionName(p_ctx, p_obj, "request_handler", 1, args,
-           &ret))
-               syslog(LOG_NOTICE,
-                   "request_handler() - JS_CallFunctionName()");
-
-err:
-       if (o != NULL)
-               server_request_object_destroy();
-}
-
-static void
-reject_handler(struct server_request *r, int res)
-{
-       JSObject        *o;
-       jsval           args[2], ret;
-
-       syslog(LOG_NOTICE, "Rejected request from [%s]",
-           r->client_address_name);
-
-       if ((o = server_request_object(r)) == NULL) {
-               syslog(LOG_NOTICE,
-                   "reject_handler() - server_request_object()");
-               goto err;
-       }
-       args[0] = OBJECT_TO_JSVAL(o);
-       args[1] = INT_TO_JSVAL(res);
-
-       if (!JS_CallFunctionName(p_ctx, p_obj, "reject_handler", 2, args,
-           &ret))
-               syslog(LOG_NOTICE, "reject_handler() - JS_CallFunctionName()");
-
-err:
-       if (o != NULL)
-               server_request_object_destroy();
-}
-
-static void
-request_close_hook(struct server_request *r)
-{
-       JSObject        *o;
-       jsval           args[1], ret;
-
-       syslog(LOG_NOTICE, "Closing for [%s]", r->client_address_name);
-
-       if ((o = server_request_object(r)) == NULL) {
-               syslog(LOG_NOTICE,
-                   "request_close_hook() - server_request_object()");
-               goto err;
-       }
-       *args = OBJECT_TO_JSVAL(o);
-
-       if (!JS_CallFunctionName(p_ctx, p_obj, "request_close_hook", 1, args,
-           &ret))
-               syslog(LOG_NOTICE,
-                   "request_close_hook() - JS_CallFunctionName()");
-
-err:
-       if (o != NULL)
-               server_request_object_destroy();
-}
-
-static void
-request_interrupt_hook(struct server_request *r)
-{
-       JSObject        *o;
-       jsval           args[1], ret;
-
-       syslog(LOG_NOTICE, "Interrupted by SIGHUP");
-
-       if ((o = server_request_object(r)) == NULL) {
-               syslog(LOG_NOTICE,
-                   "request_interrupt_hook() - server_request_object()");
-               goto err;
-       }
-       *args = OBJECT_TO_JSVAL(o);
-
-       if (!JS_CallFunctionName(p_ctx, p_obj, "request_interrupt_hook", 1,
-           args, &ret))
-               syslog(LOG_NOTICE,
-                   "request_interrupt_hook() - JS_CallFunctionName()");
-
-err:
-       if (o != NULL)
-               server_request_object_destroy();
-}
diff --git a/mmsoftware/js/js-appserv/src/js-appserv.conf.5 b/mmsoftware/js/js-appserv/src/js-appserv.conf.5
deleted file mode 100644 (file)
index 9049c74..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-.\" $Id: js-appserv.conf.5,v 1.1 2006/08/20 06:59:00 mmondor Exp $
-.\"
-.\" Copyright (C) 2006, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\" 5. Redistribution of source code may not be released under the terms of
-.\"    any GNU Public License derivate.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd June 24, 2006
-.Dt JS-CGID.CONF 5
-.Os mmsoftware
-.Sh NAME
-.Nm js-appserv.conf
-.Nd
-.Xr js-appserv.conf 5
-configuration file for
-.Xr js-appserv 8
-.Sh DESCRIPTION
-The
-.Nm /usr/local/etc/js-appserv.conf
-file may contain one or more keyword/value pairs per line, empty lines or
-comments.  A ';' or '#' character causes all other characters to be considered
-as a comment, and to be ignored, until the end of the current line. It is
-very important to enclose the value for a keyword in double quotes ('"'
-characters) if the following characters are found in it: ';', '#', space and
-tab. It is allowed to use an equal sign '=' between the keyword name and it's
-argument. Here are documented the various possible keywords and their
-allowed values, as well as their defaults.
-.Pp
-.Ss Service administration parameters
-.Pp
-.Bl -tag -width indent -offset indent
-.It Nm CHROOT_DIR Ar "directory"
-If specified and non-empty, causes the daemon to use
-.Xr chroot 2
-at initialization so that it becomes jailed into the wanted alternative root
-directory. Obviously, all required files for the application should have a copy
-within the new root (this may include files such as
-.Nm /etc/resolv.conf ,
-.Nm /etc/hosts ,
-.Nm /etc/passwd ,
-.Nm /etc/group ,
-a few shared libraries, the executable binary to be launched, and so on,
-as required by the application and libc.
-.It Nm LOCK_PATH Ar "fullpath"
-Specifies the location where the internal synchronization (and anti-recursive
-runlock) are to be created (before chrooting). Should consist of an absolute
-full pathname including a filename, after which will automatically be postfixed
-extensions for the various locks.
-When several server instances are run concurrently to serve multiple services,
-the name of the lock files should be different for each to not conflict.
-.It Nm PID_PATH Ar "fullpath"
-Tells where to store the file holding the server process ID to be killed with
-.Dv SIGTERM
-(sig 15) to cause the server to cleanly exit. This is done before chrooting.
-When several server instances are run concurrently to serve multiple services,
-the name of the PID files should be different for each to not conflict.
-.It Nm USER Ar "user"
-At server initialization, it drops privileges from the superuser to the
-specified user, definitively. This can be specified as either a username
-or it's user ID number.
-.It Nm GROUPS Ar "group,..."
-When dropping privileges, the process will become part of these groups.
-More than one group may be specified, by name or ID, separated by commas,
-without spaces. The first group will be set to the real process group, and
-others as secondary access ones.
-.It Nm LOG_FACILITY Ar "facility"
-Syslog facility which should be used for error logging. Should normally be
-one of
-.Dv LOG_AUTH , LOG_AUTHPRIV , LOG_CRON,  LOG_DAEMON ,
-.Dv LOG_FTP , LOG_KERN , LOG_LPR , LOG_MAIL ,
-.Dv LOG_NEWS , LOG_SYSLOG , LOG_USER
-or
-.Dv LOG_UUCP .
-See
-.Xr syslog 3
-man page for more information.
-.It Nm PROCTITLE Ar "string"
-This is useful if multiple services are served using
-.Xr js-appserv 8
-for commands such as
-.Xr ps 1 ,
-notably on BSD systems. Where available, this causes the supplied string
-to prefix the comments attached to the processes using
-.Xr setproctitle 3 .
-It also is appended to the daemon name for
-.Xr syslog 3
-at
-.Xr openlog 3
-time.
-.El
-.Ss TCP server administration
-.Bl -tag -width indent -offset indent
-.It Nm LISTEN_ADDRESSES Ar "address ..."
-Tells to which interfaces the server should listen to, separated by spaces.
-The arguments should be enclosed in double quotes if more than one address
-is supplied. These addresses are used for
-.Xr bind 2 .
-Specifying "0.0.0.0" causes
-.Nm js-appserv
-to listen to all interfaces.
-.It Nm LISTEN_PORT Ar "number"
-Supplies which TCP port number to listen to. This must be a numeric port number
-within the range of 1 to 65535.
-.It Nm MAX_CONNECTIONS Ar "number"
-The maximum number of simultaneous clients which should be served at once.
-.It Nm MAX_ADDRESSES Ar "number"
-The maximum number of simultaneous different client IP addresses to serve.
-.It Nm MAX_PER_ADDRESS Ar "number"
-The maximum number of simultaneous clients to serve at once per IP address.
-.It Nm CONNECTION_RATE Ar "number"
-The maximum number of connections to accept from each address within
-.Nm CONNECTION_PERIOD .
-Can be 0 to disable connection rate throttling.
-.It Nm CONNECTION_PERIOD Ar "number"
-If
-.Nm CONNECTION_RATE
-is non-zero, specifies the number of seconds during which a maximum of
-.Nm CONNECTION_RATE
-connections are to be allowed.
-.It Nm RESOLVE_ADDRESSES Ar "boolean"
-Specifies weither client addresses should be resolved to hostnames when
-logging the connection event via
-.Xr syslog 3 .
-An internal cache is maintained for recently connected addresses for faster
-performance. This is done in the child serving process so that it does not
-slow down the listener process responsible for accepting new connections.
-Should be TRUE or FALSE.
-.El
-.Ss Application security limits
-.Bl -tag -width indent -offset indent
-.It Nm RLIMITS Ar "boolean"
-If TRUE, all following
-.Nm RLIMIT_*
-parameters will be applied to the children processes before launching the
-application command if they are not set to -1 values.
-.Xr setrlimit 2
-is called to perform this. Note that these should be set to sane values
-for proper function, by a competent administrator, if this option is
-enabled. When disabled, or if enabled but for each following option specified
-with -1, the defaults are used, which are inherited from the server process.
-.Bl -tag -width indent -offset indent
-.It Nm RLIMIT_CORE Ar "value"
-If not -1, the largest size (in bytes) core file that may be created.
-.It Nm RLIMIT_CPU Ar "value"
-If not -1, The maximum amount of cpu time (in seconds) to be used by
-each process.
-.It Nm RLIMIT_DATA Ar "value"
--1 or The maximum size (in bytes) of the data segment for a process;
-this defines how far a program may extend its break with the
-.Xr sbrk 2
-or
-.Xr mmap 2
-system calls.
-.It Nm RLIMIT_FSIZE Ar "value"
-The largest size (in bytes) file that may be created, or -1.
-.It Nm RLIMIT_MEMLOCK Ar "value"
-The maximum size (in bytes) which a process may lock into physical memory
-(wire) using the
-.Xr mlock 2
-system call function, or -1.
-.It Nm RLIMIT_NOFILE Ar "value"
-If not -1, the maximum number of open files for this process.
-.It Nm RLIMIT_NPROC Ar "value"
-The maximum number of simultaneous processes for this user ID, or -1.
-.It Nm RLIMIT_RSS Ar "value"
-The maximum size (in bytes) to which a process's resident
-set size may grow.  This imposes a limit on the amount of
-physical memory to be given to a process; if memory is
-tight, the system will prefer to take memory from processes
-that are exceeding their declared resident set size.
--1 to use the defaults.
-.It Nm RLIMIT_STACK Ar "value"
-If not -1, the maximum size (in bytes) of the stack segment for a
-process; this defines how far a program's stack segment
-may be extended.  Stack extension is performed automatically by the system.
-.El
-.El
-.Ss Debugging support
-.Bl -tag -width indent -offset indent
-.It Nm STDERR_FILE Ar "fullpath"
-XXX
-By default, the standard error stream (stderr) of
-.Nm COMMAND
-is redirected to the "/dev/null" device. However, it may be nice to be able
-to obtain those messages from time to time, or to see if any are generated
-by the application. This option, if non-empty, creates, or appends to the
-specified file (outside of the chroot setup). This option should not be
-used on production systems, as the file will grow without bounds. If a log
-rotation system is used,
-.Xr js-appserv 8
-will require to be restarted everytime it is ran. It is merely for debugging.
-.El
-.Sh DEFAULTS
-The following defaults are used:
-.Pp
-.Bd -literal -offset indent
-CHROOT_DIR             ""
-LOCK_PATH              "/var/run/js-appserv.lock"
-PID_PATH               "/var/run/js-appserv.pid"
-USER                   "js-appserv"
-GROUPS                 "js-appserv"
-LOG_FACILITY           "LOG_AUTHPRIV"
-PROCTITLE              ""
-
-LISTEN_ADDRESSES       "127.0.0.1"
-LISTEN_PORT            2323
-MAX_CONNECTIONS                32
-MAX_ADDRESSES          32
-MAX_PER_ADDRESS                1
-CONNECTION_RATE                5
-CONNECTION_PERIOD      30
-RESOLVE_ADDRESSES      FALSE
-
-RLIMITS                        FALSE
-RLIMIT_CORE            -1
-RLIMIT_CPU             -1
-RLIMIT_DATA            -1
-RLIMIT_FSIZE           -1
-RLIMIT_MEMLOCK         -1
-RLIMIT_NOFILE          -1
-RLIMIT_NPROC           -1
-RLIMIT_RSS             -1
-RLIMIT_STACK           -1
-
-STDERR_FILE            ""
-.Ed
-.Sh AUTHOR
-.Nm js-appserv
-was written by Matthew Mondor, and is
-Copyright (c) 2006, Matthew Mondor, All rights reserved.
-.Sh FILES
-.Bl -tag -width indent -offset indent
-.It Pa /usr/local/etc/js-appserv.conf
-This file
-.It Pa /usr/local/sbin/js-appserv
-The
-.Xr js-appserv 8
-server binary itself.
-.El
-.Sh SEE ALSO
-.Xr js-appserv 8 ,
-.Xr syslog 3 ,
-.Xr openlog 3 ,
-.Xr chroot 2 ,
-.Xr bind 2 ,
-.Xr setrlimit 2 ,
-.Xr ps 1 ,
-.Xr setproctitle 3 .
-.Sh BUGS
-Not really a bug, but tied to each interface could be most connection control
-options.
-.Pp
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/js/js-sh/app/httpd/httpd.js b/mmsoftware/js/js-sh/app/httpd/httpd.js
deleted file mode 100644 (file)
index e5f23e7..0000000
+++ /dev/null
@@ -1,2089 +0,0 @@
-/* $Id: httpd.js,v 1.46 2006/11/26 05:58:55 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005-2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Little example showing the versatility of ECMAScript, provided with a
- * custom library for BSD socket support, using SpiderMonkey.
- * This tiny HTTPd allows simultaneous concurrent client connections without
- * using multiple threads or processes.  Must be ran through js-sh.
- *
- * Configuration options can be found in options.js
- *
- * XXX Possibly that with close var semantics changes or such, we could
- * support Keep-Alive for HTTP/1.1 connections.  This however is not a
- * priority at current time.
- *
- * TODO:
- * - For efficiency the FD C class probably should return -1 with error
- *   or such rather than throwing exceptions.  This would also minimize the
- *   many try/catch ugly blocks.
- * - Read http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
- *   and see if we meet conformance, adjust as needed.
- * - We might want to check Accept-Language: for multilingual sites...
- * - See what to do for HEAD and PUT
- * - Possibly limit rate of connections per address like I did in
- *   mmftpd/mmsmtpd/mmpop3d/mmspawnd, a requested feature of 3s4i.
- *   If enabling this, it probably should be per-vhost configurable.
- *   I'm not sure HTTP protocol is well suited to this type of limiting,
- *   some testing will be required.
- * - Implement logging
- * - Enhance the JS shell to report errors better
- *
- * Transfer states
- * - file to client, must take into account client connection status.
- * - client to appserv, appserver to client, must take into account both
- *   client and appserv connections status.
- * Both states must use a transitional read/write buffer.
- *
- * File to client state
- * 1) read(2) form file to buffer, switch to write/POLLOUT to client
- * 2) write(2) to client, switch to (1) again, or stop
- * 3) stop, do state change or close...
- *
- * Client to appserv request
- * - read(2) request from client
- * - Connect to appserv if required, send initial request to appserv
- * - if necessary read result from appserv
- * 1) read(2) from client, filling buffer, switch to write/POLLOUT to appserv
- * 2) write(2) to appserv, switch to (1) again, or stop
- * 3) read(2) from appserv, filling buffer, switch to write/POLLOUT to client
- * 4) write(2) to client, switch to (3) again or stop
- *
- * ---
- * For performance and efficiency, a state switch should be done by changing
- * the process/state function reference.  The less conditionals each of these
- * functions can perform, the more efficient.
- * When possible, it is nice to be able to chain a read/write phase into the
- * same FD event processing session (such as state_http_transfer_file() does).
- * Nevertheless, these require a transitional buffer.
- *
- * - client fd -> appserv connect state
- * - file to client, must take into account client connection status
- *   (state_http_transfer_file()).
- * - client to appserv, must take into account both connections status
- *   (state_http_transfer_toappserv()). client == POLLIN, appserv == POLLOUT
- * - appserv to client, must take into account both connections status
- *   (state_http_transfer_fromappserv()). appserv == POLLIN, client == POLLOUT
- */
-
-
-
-/*
- * Server identification
- */
-const SERVER_VERSION = 'mmondor_js_httpd/0.2.1 (NetBSD)';
-const SERVER_CVSID = '$Id: httpd.js,v 1.46 2006/11/26 05:58:55 mmondor Exp $';
-
-
-
-/*
- * Import needed functionality from external modules, since #include is
- * missing :)
- */
-function file_read(file)
-{
-       var contents = '';
-       var data;
-       var fd;
-
-       try {
-               /*
-                * If we were provided with a filename, rather than a
-                * filedescriptor object, open the filename.  Otherwise,
-                * read from the specified FD.
-                */
-               if (typeof file != 'object') {
-                       fd = new FD();
-                       fd.open(file, FD.O_RDONLY);
-               } else
-                       fd = file;
-       } catch (x) {
-               stderr.write(x + " at file_read()\n");
-       }
-
-       try {
-               for (;;) {
-                       data = fd.read(65536);
-                       if (data.length == 0)
-                               break;
-                       contents += data;
-               }
-       } catch (x) {
-               stderr.write(x + " at file_read()\n");
-       }
-
-       fd.close();
-
-       return contents;
-}
-
-try {
-       eval(file_read('options.js'));          /* Configuration */
-} catch (x) {
-       stderr.write(x + " while reading options file\n");
-       exit();
-}
-eval(file_read(ilibprefix + 'fd.js'));
-eval(file_read(ilibprefix + 'string.js'));
-eval(file_read(ilibprefix + 'ml_machine.js'));
-eval(file_read(ilibprefix + 'root.js'));
-
-
-
-/*
- * Socket types (enumeration)
- */
-const STYPE_LISTEN             = 0;
-const STYPE_CONNECT            = 1;
-const STYPE_HTTP               = 2;
-const STYPE_APPSERV            = 3;
-/*
-const STYPE_LDEBUG             = 4;
-const STYPE_DEBUG              = 5;
-*/
-
-/*
- * Client file transfer states (enumeration)
- */
-const TSTATE_READ              = 0;
-const TSTATE_WRITE             = 1;
-
-/*
- * General status return for state functions
- */
-const PSTAT_CONTINUE           = 0;
-const PSTAT_CLOSE_SUCCESS      = 1;
-const PSTAT_CLOSE_ERROR                = 2;
-
-
-
-/*
- * Quick lookup object from virtual hosts names and aliases to VHost objects
- */
-var vhosts_table = {};
-var default_vhost = undefined;
-
-/*
- * The VHost object
- */
-function VHost(o)
-{
-       var i;
-
-       /*
-        * A few properties are definitely required
-        */
-       if (o.name == undefined || o.root == undefined)
-               throw ('name and root properties missing from vhost');
-       o.name = o.name.toLowerCase();
-       this.name = o.name;
-
-       if (o.appserv != undefined) {
-               if (o.appserv.paths_cache_max == undefined ||
-                   o.appserv.paths_cache_max < 0)
-                       throw ('paths_cache_max missing from appserv or ' +
-                           'invalid');
-               if (o.appserv.paths == undefined || o.appserv.paths.length < 1)
-                       throw ('paths missing from appserv');
-               if (o.appserv.servers == undefined || o.appserv.servers < 1)
-                       throw ('servers missing from appserv');
-               /*
-                * Used for faster lookups, faster than match().
-                * A URL object is cached with true if matches, false if not.
-                * If full, the cache is destroyed and restarted.  This will
-                * pevent cache poisoning issues which could be exploited for
-                * denial of service attacks.
-                */
-               o.appserv.paths_cache = {};
-               o.appserv.paths_cache_items = 0;
-               /*
-                * Used for load distribution among js-appserv(s).
-                * List will be sorted by average time to respond to a request
-                * to enhance performance resending requests to faster
-                * servers.  If a server can no longer accept more clients, it
-                * also will be avoided until it's free again.
-                */
-               for (i in o.servers) {
-                       if (o.servers[i].host == undefined)
-                               throw ('host missing from server object');
-                       if (o.servers[i].port == undefined)
-                               throw ('port missing from server object');
-                       if (o.servers[i].clients == undefined)
-                               throw ('clients missing from server object');
-                       o.servers[i].free_slots = o.servers[i].clients;
-                       o.servers[i].ms_avg = 0;
-                       o.servers[i].ms_total = 0;
-                       o.servers[i].ms_count = 0;
-                       /* XXX
-                        * To be turned off for long timeing out js-appserv
-                        * after logging the issue.
-                        */
-                       o.servers[i].valid = true;
-               }
-               this.appserv = o.appserv;
-       }
-
-       /*
-        * Create VHost object
-        */
-       try {
-               this.htdocs_root = new Root(o.root);
-       } catch (x) {
-               throw (x);
-       }
-
-       this.index = (o.index != undefined ? o.index : options.default_index);
-       this.charset = (o.charset != undefined ? o.charset :
-           options.default_charset);
-
-       /*
-        * Link object to vhosts table
-        */
-       if (vhosts_table[o.name] != undefined)
-               throw ('Conflicting vhost name: ' + o.name);
-       vhosts_table[o.name] = this;
-
-       /*
-        * Also provide links for vhost aliases
-        */
-       if (o.aliases != undefined) {
-               for (i in o.aliases) {
-                       o.aliases[i] = o.aliases[i].toLowerCase();
-                       if (vhosts_table[o.aliases[i]] != undefined)
-                               throw ('Conflicting vhost alias: ' +
-                                   o.aliases[i]);
-                       vhosts_table[o.aliases[i]] = this;
-               }
-       }
-}
-
-VHost.prototype = {
-       /*
-        * Utility function internally used by server_ms_account()
-        */
-       serv_ms_compare: function(a, b)
-       {
-               if (a.ms_avg < b.ms_avg)
-                       return -1;
-               if (a.ms_avg > b.ms_avg)
-                       return 1;
-               return 0;
-       },
-
-       /*
-        * Account ms taken for last request and resort priority array if
-        * necessary.
-        */
-       server_ms_account: function(s, ms)
-       {
-               var o = this.appserv.servers[i];
-               s.ms_total += ms;
-               if (++s.ms_count == this.appserv.servers.length) {
-                       s.ms_avg = s.ms_total / s.ms_count;
-                       s.ms_total = s.ms_count = 0;
-                       this.appserv.servers.sort(serv_ms_compare);
-               }
-       },
-
-       /*
-        * Choose a server to next connect to, taking in consideration the
-        * average ms per request and the number of clients connected to each
-        * server.  This allows to perform load balancing among them.
-        * This returns a reference to a server object within the servers
-        * array, which remains valid even when sorting the array.
-        * Returns undefined if no more client slots remain.
-        */
-       server_get: function()
-       {
-               var a = this.appserv.servers;
-               var s = undefined;
-
-               for (i in a) {
-                       if (a[i].free_slots > 0 && a[i].valid) {
-                               s = a[i];
-                               s.free_slots--;
-                               break;
-                       }
-               }
-
-               if (s == undefined)
-                       stderr.write("No more free appserv slots\n");
-
-               return s;
-       },
-
-       /*
-        * Releases a server;  updates currently connected number of clients
-        */
-       server_put: function(s)
-       {
-               s.free_slots++;
-       },
-
-       /*
-        * Returns true if the specified path matches one of the appserv
-        * paths matching patterns, or false otherwise.  Also maintains a
-        * cache for efficiency since an object properly lookup is faster than
-        * regexp matching.
-        * Note: path should already be free of GET variables.
-        */
-       host_appmatch: function(p)
-       {
-               var b, o;
-               var appserv = this.appserv;
-
-               b = false;
-
-               if (appserv == undefined)
-                       return b;
-
-               o = appserv.paths;
-
-               if (appserv.paths_cache[p] != undefined)
-                       return appserv.paths_cache[p];
-
-               if (++appserv.paths_cache_items == appserv.paths_cache_max) {
-                       appserv.paths_cache = {};
-                       appserv.paths_cache_items = 1;
-               }
-               for (i in o) {
-                       if (p.match(o[i]))
-                               b = true;
-               }
-               appserv.paths_cache[p] = b;
-
-               return b;
-       }
-}
-
-
-
-/*
- * Quick SID->appserv FD lookup table
- */
-var sid_table = {};
-
-
-
-/*
- * For the mime types database
- */
-var mimetypes_table = {};
-
-
-
-/*
- * The HTTPReply object allows to cache addHeader() and addContent() requests,
- * and to eventually flush the whole reply to an arbitrary FD afterwards.
- */
-
-/*
- * Constructor
- */
-function HTTPReply(code, desc, type)
-{
-       this.code = code;
-       this.desc = desc;
-       this.headers = [];
-       this.contents = [];
-       this.type = type;
-
-       /*
-        * Insert our standard headers.
-        */
-       this.gmttime = (new Date()).toGMTString();
-       this.headers.push('Date: ' + this.gmttime);
-       this.headers.push('Server: ' + SERVER_VERSION);
-       this.headers.push('Connection: close');
-       this.headers.push('Accept-Ranges: bytes');
-}
-/*
- * HTTPReply prototype object
- */
-HTTPReply.prototype = {
-       setType: function(type)
-       {
-
-               this.type = type;
-       },
-
-       addHeader: function(data)
-       {
-
-               this.headers.push(data);
-       },
-
-       addNoCacheHeaders: function()
-       {
-
-               this.headers.push('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
-               this.headers.push('Last-Modified: ' + this.gmttime);
-               this.headers.push('Cache-Control: no-cache, must-revalidate');
-               this.headers.push('Pragma: no-cache');
-       },
-
-       addContent: function(data)
-       {
-
-               this.contents.push(data);
-       },
-
-       flush: function(fd, size)
-       {
-               var headers = '';
-               var contents = '';
-               var i, t;
-
-               for (i = 0; i < this.contents.length; i++)
-                       contents += this.contents[i];
-
-               t = new Date();
-               Syslog.log(Syslog.LOG_NOTICE, fd.client_addr + ' - - ' +
-                   http_log_date() + ' ' + fd.http_vhost.name + ' "' +
-                   fd.http_request + '" ' + this.code + ' ' +
-                   contents.length + ' "' + fd.http_referer + '" "' +
-                   fd.http_agent + '"');
-
-               this.headers.push('Content-Length: ' +
-                   (size == null ? contents.length : size));
-               if (options.debug == true)
-                       stdout.write(' --> ' + this.code + ' ' +
-                           this.headers.toSource() + "\n");
-               headers += 'HTTP/1.1 ' + this.code + ' ' + this.desc + "\r\n";
-               for (i = 0; i < this.headers.length; i++)
-                       headers += this.headers[i] + "\r\n";
-               if (this.type != null)
-                       headers += 'Content-Type: ' + this.type + "\r\n";
-               headers += "\r\n";
-
-               if (!fd.http_old_get)
-                       fd.bwrite(headers + contents, true, false);
-               else
-                       fd.bwrite(contents, true, false);
-       }
-}
-
-/*
- * Generates an error page and sends it to specified FD object.
- */
-function http_error(fd, code, desc, ldesc)
-{
-       var res = new HTTPReply(code, desc, 'text/html; charset=' +
-           options.default_charset);
-       res.addNoCacheHeaders();
-
-       res.addContent('<html><head><title>' + code + ' ' + desc +
-           '</title></head><body><h1>' + code + ' ' + desc + '</h1>' +
-           '<p>' + ldesc + '</p><br>');
-
-       if (options.debug == true)
-               res.addContent(fd.httpDebug());
-
-       res.addContent('<br><sub>' + SERVER_VERSION + '<br>' + SERVER_CVSID +
-           '</sub></body></html>');
-
-       res.flush(fd, null);
-}
-
-/*
- * Redirects the HTTP client to another path.
- */
-function http_redirect(fd, vpath)
-{
-       var res, path;
-
-       if (!(path = fd.http_vhost.htdocs_root.valid_virtual(vpath))) {
-               http_error(this, 403, 'Permission Denied',
-                   'You do not have the permission to access this ' +
-                   'resource.');
-               return;
-       }
-
-       res = new HTTPReply(301, 'Moved Permanently',
-           'text/html; charset=' + options.default_charset);
-       res.addNoCacheHeaders();
-
-       res.addHeader('Location: http://' + fd.http_host + path.virtual);
-       res.addContent('<html><head><title>301 Moved Permanently</title>' +
-           '</head><body><h1>301 Moved Permanently</h1><p>The document was ' +
-           'permanently moved<a href="http://' + fd.http_host + path.virtual +
-           '">here</a>.</p></body></html>');
-
-       res.flush(fd, null);
-}
-
-
-function http_log_init()
-{
-       var i;
-
-       /* XXX Make facility configurable */
-       Syslog.open('js-httpd', Syslog.LOG_PID | Syslog.LOG_NDELAY,
-           Syslog.LOG_AUTH);
-
-       http_log_months = [
-          'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
-          'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
-
-       http_log_digits = [];
-       for (i = 0; i < 60; i++) {
-               if (i < 10)
-                       http_log_digits[i] = '0' + i;
-               else
-                       http_log_digits[i] = i;
-       }
-
-       http_log_zone = (new Date).getTimezoneOffset() / 60;
-       if (http_log_zone > 0) {
-               if (http_log_zone < 10)
-                       http_log_zone = '0' + http_log_zone;
-               http_log_zone = '+' + http_log_zone;
-       } else {
-               http_log_zone = http_log_zone.toString();
-               if (http_log_zone.length < 3)
-                       http_log_zone = '-0' + http_log_zone.charAt(1);
-       }
-       http_log_zone += '00';
-}
-
-function http_log_date()
-{       
-       var t = new Date();
-       var s = '[' + t.getDate() + '/' + http_log_months[t.getMonth()] + '/' +
-           (1900 + t.getYear()) + ':' + http_log_digits[t.getHours()] + ':' +
-           http_log_digits[t.getMinutes()] + ':' +
-           http_log_digits[t.getSeconds()] + ' ' +
-           http_log_zone + ']';
-
-       return s;
-}
-
-
-/*
- * Add new methods to the FD prototype object (JavaScript is great like that).
- * We need to add these properties one by one to the prototype object of FD,
- * since we wouldn't want to override its default prototype, just expand it.
- */
-
-/*
-function state_debug_read(time)
-{
-       var data;
-
-       while ((data = this.breadline(255, false)) != null) {
-               if (data.length > 0) {
-                       this.bwrite('you typed: "' + data + '"' + "\n",
-                           true, false);
-               } else
-                       break;
-       }
-       if (data == null) {
-               if (this.berror != this.BEAGAIN) {
-                       stderr.write(this.berrorStr[this.berror] +
-                           " at state_debug_read()\n");
-                       return PSTAT_CLOSE_SUCCESS;
-               }
-       }
-
-       return PSTAT_CONTINUE;
-}
-*/
-
-/*
- * Reset FD to a consistent known state, to use after accept(2).
- * To be passed current time in seconds since epoch.
- */
-FD.prototype.state_http_init = function(time)
-{
-       /* For differenciation after poll(2) */
-       this.type = STYPE_HTTP;
-       this.stat = PSTAT_CONTINUE;
-
-       /* Empty request */
-       this.query_data = [];
-       this.query_data_length = 0;
-
-       /*
-        * Events interested in.  FD.POLLOUT to be eventually used instead in
-        * transfer state if transfering from server to client.
-        */
-       this.events = FD.POLLIN;
-       /*
-        * Default handler to process this FD, the request state one.
-        * To be changed to the transfer one as needed for transfer state.
-        */
-       this.state = state_http_query_get;
-       /* Initial input timeout */
-       this.updateTimeout(time);
-
-       /*
-        * Note that fcntl(2) and setsockopt(2) flags applied to the bound
-        * descriptors are inherited to their children sockets at accept(2).
-        * We therefore can save a few syscalls here.
-        * We are non-blocking already, for instance.
-        */
-}
-
-/*
- * Handles request query processing, to be assigned to FD.state() while in
- * the request query state.  This then invokes parseQuery() which may
- * either send an HTTP response and/or cause a switch to another state.
- */
-function state_http_query_get(time)
-{
-       var done = false;
-       var stat = PSTAT_CONTINUE;
-       var data, w;
-
-       /*
-        * Read lines buffering, until a maximum of options.max_query_size
-        * length.  Close connection on error.  Upon receiving a terminating
-        * empty line, or a two fields old-style GET request as the first
-        * line, proceed with the query.
-        *
-        * If continueing, parse query to modify state accordingly, and let
-        * the parsing method decide if we'll close the connection.
-        */
-       while ((data = this.breadline(options.max_query_size -
-           this.query_data_length, false)) != null) {
-               this.updateTimeout(time);
-               if (data.length > 0) {
-                       this.query_data.push(data);
-                       this.query_data_length += data.length + 2;
-                       if (this.query_data.length == 1) {
-                               w = data.split(' ');
-                               if (w.length == 2 && w[0] == 'GET') {
-                                       /* Old-style GET */
-                                       done = true;
-                                       break;
-                               }
-                       }
-               } else {
-                       /* End of query */
-                       done = true;
-                       break;
-               }
-       }
-       if (data == null) {
-               /* Error */
-               if (this.berror != this.BEAGAIN) {
-                       /* XXX */ stderr.write(this.berrorStr[this.berror]
-                           + "\n");
-                       if (this.berror == this.BTOOLONG)
-                               http_error(this, 413,
-                                   'Request Entity Too Large',
-                                   'Query length exceeds ' +
-                                   options.max_query_size + ' bytes.');
-                       return PSTAT_CLOSE_SUCCESS;
-               }
-               /* Must poll */
-               return PSTAT_CONTINUE;
-       }
-
-       if (done)
-               stat = this.parseQuery(time);
-
-       return stat;
-}
-
-function state_http_post_get(time)
-{
-       var stat = PSTAT_CONTINUE;
-       var len;
-       var data;
-
-       if (this.post_data.length < this.http_content_length) {
-               len = this.http_content_length - this.post_data.length;
-               if ((data = this.bread(len, false)) == null) {
-                       if (this.berror != this.BEAGAIN) {
-                               /* XXX */ stderr.write(
-                                   this.berrorStr[this.berror] + "\n");
-                               return PSTAT_CLOSE_ERROR;
-                       }
-               }
-               this.post_data += data;
-               this.updateTimeout(time);
-       } else
-               stat = this.parsePost(time);
-
-       return stat;
-}
-
-/*
- * Handles transfer processing from an open file to an open client descriptor,
- * to be assigned to FD.state() while in the transfer state.
- */
-function state_http_transfer_file(time)
-{
-       var stat = PSTAT_CONTINUE;
-       var bufsiz;
-
-       /*
-        * TSTATE_READ specifies that we're reading to the buffer from
-        * transfer_src, or TSTATE_WRITE that we're writing from the buffer
-        * to transfer_dst.  We can do both steps one after another if
-        * possible.
-        * On EAGAIN errors, simply pass our turn to go back to
-        * polling.  On EOF reading from either end, exit transfer
-        * state after writing to the other and syncing/closing,
-        * and order to close client descriptor.
-        * We take care not to transfer more than this.transfer_size.
-        */
-       if (this.transfer_state == TSTATE_READ) {
-               /* Reading from file */
-               bufsiz = this.transfer_size;
-               if (bufsiz > options.file_buf_size)
-                       bufsiz = options.file_buf_size;
-               try {
-                       if (bufsiz > 0)
-                               this.transfer_data =
-                                   this.transfer_src.read(bufsiz);
-                       else
-                               this.transfer_data = '';
-                       if (this.transfer_data.length == 0)
-                               this.transfer_eof = true;
-                       this.transfer_size -= this.transfer_data.length;
-                       this.transfer_state = TSTATE_WRITE;
-               } catch (x) {
-                       stat = PSTAT_CLOSE_ERROR;
-               }
-       }
-       if (this.transfer_state == TSTATE_WRITE) {
-               /* Writing to client */
-               if (this.transfer_eof)
-                       stat = PSTAT_CLOSE_SUCCESS;
-               else {
-                       /*
-                        * XXX For some reason, we now get problems with
-                        * immediate writing mode.  Dandling client and file
-                        * descriptors remain, like if HUP was ignored.
-                        * Very odd.
-                        */
-                       if (this.bwrite(this.transfer_data, false, false)
-                           != -1) {
-                               this.transfer_state = TSTATE_READ;
-                               this.updateTimeout(time);
-                       } else {
-                               if (this.berror == this.BEAGAIN)
-                                       this.events |= FD.POLLOUT;
-                               else
-                                       stat = PSTAT_CLOSE_ERROR;
-                       }
-               }
-       }
-
-       /* Currently redundant unless we supported Keep-Alive
-       if (stat != PSTAT_CONTINUE) {
-               try {
-                       this.transfer_src.close();
-               } catch (x) {}
-       }
-       */
-
-       return stat;
-}
-
-/*
- * Set a few HTTP parsing defaults as part of the prototype for efficiency
- * (they get inherited using COW)
- */
-
-/*
- * Updates input timeout expiration time for this FD.
- * To be passed current time in seconds since epoch.
- */
-FD.prototype.updateTimeout = function(time)
-{
-       /* Update input timeout expiration time */
-       this.expires = time + options.io_timeout;
-}
-
-/*
- * To be called once our client request has been read, to decide what action
- * to perform and modify state accordingly.
- */
-FD.prototype.parseQuery = function(time)
-{
-       var stat = PSTAT_CONTINUE;
-       var valid = false;
-       var evil_browser = evil_os = false;
-       var vhost = '';
-       var lines;
-       var words, w;
-       var i;
-       /*
-       var sessid, sess;
-       */
-
-       /* Initial HTTP query state */
-       this.http_protocol = '';
-       this.http_method = '';
-       this.http_request = undefined;
-       this.http_vhost = this.http_host = 'n/a';
-       this.http_path = '';
-       this.http_vars_get = {};
-       this.http_vars_post = {};
-       this.http_vars_cookies = {};
-       this.http_vars_cookies_count = 0;
-       this.http_agent = '-';
-       this.http_content_length = -1;
-       this.http_modified_since = undefined;
-       /*
-       this.http_sessid = undefined;
-       */
-       this.http_range = undefined;
-       this.http_referer = '-';
-       this.http_old_get = false;
-
-       /* Split request lines */
-       lines = this.query_data;
-       if (options.debug == true)
-               stdout.write(this.client_addr + ':' + this.client_port + ' ' +
-                   lines.toSource());
-
-       /* Verify if first line has a request which seems valid */
-       if (lines.length > 0) {
-               this.http_request = lines[0];
-               words = lines[0].split(' ');
-               if (words.length == 2 && words[0] == 'GET') {
-                       this.http_method = words[0];
-                       this.http_path = words[1];
-                       this.http_protocol = 'HTTP/1.1';
-                       this.http_old_get = true;
-                       valid = true;
-               } else if (words.length == 3) {
-                       if ((words[0] == 'GET' || words[0] == 'POST' ||
-                           words[0] == 'PUT') && (words[2] == 'HTTP/1.0' ||
-                           words[2] == 'HTTP/1.1')) {
-                               this.http_method = words[0];
-                               this.http_path = words[1];
-                               this.http_protocol = words[2];
-                               valid = true;
-                       }
-               }
-       }
-
-       /*
-        * Parse header for interesting lines.
-        * The element name is case-insensitive.
-        */
-       if (valid && !this.http_old_get) {
-               for (i in lines) {
-                       words = lines[i].split(' ');
-                       w = words[0].toLowerCase();
-                       if (w == 'host:' && words.length == 2) {
-                               var i2;
-
-                               this.http_host = words[1];
-                               if ((i2 = words[1].indexOf(':')) != -1)
-                                       words[1] = words[1].substr(0, i2);
-                               vhost = words[1];
-                       } else if (w == 'cookie:') {
-                               words = (lines[i].substr(8)).split('=');
-                               if (words.length == 2) {
-                                       property_add(this.http_vars_cookies,
-                                           words[0], words[1]);
-                                       this.http_vars_cookies_count++;
-                               }
-                       } else if (w == 'user-agent:') {
-                               this.http_agent = lines[i].substr(12);
-                               if (options.ban_msie == true &&
-                                   this.http_agent.indexOf('MSIE') != -1)
-                                       evil_browser = true;
-                               if (options.ban_windows == true &&
-                                   this.http_agent.indexOf('Windows') != -1)
-                                       evil_os = true;
-                       } else if (w == 'content-length:' && words.length == 2)
-                               this.http_content_length = words[1].valueOf();
-                       else if (w == 'if-modified-since:')
-                               this.http_modified_since = Math.round(
-                                   Date.parse(lines[i].substr(19)) / 1000);
-                       else if (w == 'range:')
-                               this.http_range = lines[i].substr(7);
-                       else if (w == 'referer:')
-                               this.http_referer = lines[i].substr(9);
-               }
-       }
-
-       /*
-        * If no Host: line set the vhost, set the default one.
-        * If there is a vhost set, but is unknown, also set the default one.
-        * Also set the name of the vhost to the actual vhost name despite
-        * it possibly being resolved through an alias.
-        */
-       if (vhost == '' || vhosts_table[vhost] == undefined)
-               vhost = options.default_vhost;
-       this.http_vhost = vhosts_table[vhost.toLowerCase()];
-
-       if (this.http_old_get && this.http_vhost.appserv != undefined) {
-               /*
-                * We only allow old style GET request on static vhosts
-                */
-               http_error(this, 505, 'HTTP Version not supported',
-                   'Old-Style HTTP requests unsupported by this virtual ' +
-                   'host since it supports dynamic content generation.');
-               return PSTAT_CLOSE_SUCCESS;
-       }
-
-       /*
-        * Filter out definitely invalid requests
-        */
-       if (!valid) {
-               http_error(this, 400, 'Bad Request',
-                   'Your browser sent an invalid HTTP query.');
-               return PSTAT_CLOSE_SUCCESS;
-       }
-
-       if (this.http_content_length != -1 &&
-           this.http_content_length > options.max_post_size) {
-               http_error(this, 413, 'Request Entity Too Large',
-                   'POST Content-Length exceeds ' + options.max_post_size +
-                   ' bytes.');
-               return PSTAT_CLOSE_SUCCESS;
-       }
-
-       /*
-        * Block out evil Microsoft products.  Start reporting the OS
-        * so that an unwanted windows user doesn't install another
-        * browser to then realize that his OS is banned nevertheless :)
-        */
-       if (evil_os) {
-               http_error(this, 666, 'Evil Operating System Banished!',
-                   'Your Operating System is evil born.<br>At least ' +
-                   '<b>upgrade</b> to a <a href="http://netbsd.org">' +
-                   'decent</a> OS to survive on these grounds.<br>');
-               return PSTAT_CLOSE_SUCCESS;
-       } else if (evil_browser) {
-               http_error(this, 666, 'Evil Browser Banished!',
-                   'Your browser is evil born.<br>At least ' +
-                   '<b>upgrade</b> to a <a href="http://mozilla.org">' +
-                   'decent</a> browser to survive on these grounds.<br>');
-               return PSTAT_CLOSE_SUCCESS;
-       }
-
-       /*
-        * Fill in associative array with any GET-style supplied
-        * variables (as part of the URL).  We want this even for POST method.
-        * XXX We might need to account for vars without content, and for %xx
-        * characters...
-        */
-       if ((i = this.http_path.lastIndexOf('?')) != -1) {
-               var v;
-               var t;
-
-               v = this.http_path.substr(i + 1);
-               /*
-                * Note: substring() and substr() are semantically different
-                */
-               this.http_path = this.http_path.substring(0, i);
-               words = v.split('&');
-               for (i in words) {
-                       t = words[i].split('=');
-                       if (t.length == 2)
-                               property_add(this.http_vars_get, t[0], t[1]);
-               }
-       }
-
-       /*
-        * Switch to POST parsing mode if needed.
-        * This will then call this.parsePost() rather than this function,
-        * which will also invoke this.httpRespond().
-        * XXX POST will need to be transfered from client to appserv
-        * directly.
-        */
-       if (this.http_method == 'POST' && this.http_content_length != -1) {
-               /*
-                * Switch to state_http_post_get() state.  Invoke it ourselves
-                * at least once to empty the read buffer if any, then go back
-                * to polling.  If that first call is enough to satisfy the
-                * needed size, immediately call parsePost() which will return
-                * close status after invoking httpRespond().
-                */
-               this.post_data = '';
-               this.state = state_http_post_get;
-               if (!this.state(time))
-                       return PSTAT_CONTINUE;
-               if (this.post_data.length == this.http_content_length)
-                       return this.parsePost(time);
-               /* Go back to polling under state_http_post_get() state */
-               return PSTAT_CONTINUE;
-       }
-
-       /* XXX Condition would always be true here at current time */
-       if (stat == PSTAT_CONTINUE)
-               stat = this.httpRespond(time);
-
-       return stat;
-}
-
-/*
- * After reading post data, allows to parse it down into variables
- */
-FD.prototype.parsePost = function(time)
-{
-       var words;
-       var i;
-       var t;
-
-       /*
-        * We need to strip "\n", "\r" and "\r\n" which may be sent by broken
-        * clients.
-        */
-       this.post_data = this.post_data.replace(/\n/g, '');
-       this.post_data = this.post_data.replace(/\r/g, '');
-
-       words = this.post_data.split('&');
-       for (i in words) {
-               t = words[i].split('=');
-               if (t.length == 2)
-                       property_add(this.http_vars_post, t[0], t[1]);
-       }
-
-       delete this.post_data;
-
-       return this.httpRespond(time);
-}
-
-/*
- * Finally respond to client request
- */
-FD.prototype.httpRespond = function(time)
-{
-       var path, fd, st, res, ext, mimetype, i, size, appserv_match, doc;
-       /*
-       var sess;
-       */
-
-       /*
-        * Verify if requested path is valid
-        */
-       path = this.http_vhost.htdocs_root.valid_virtual(this.http_path);
-       if (!path) {
-               http_error(this, 403, 'Permission Denied',
-                   'You do not have the permission to access this ' +
-                   'resource.');
-               return PSTAT_CLOSE_SUCCESS;
-       }
-
-       /*
-        * General strategy:
-        * 1) Verify if path matches appserver.  If not, attempt to open file,
-        *    return 404 or 403 on failure.
-        *    On success, if it consists of a directory, apply index path,
-        *    match again against appserver paths, close fd and forward to
-        *    appserver also if so.  If not, close dir fd and attempt to open
-        *    again after applying index.  On failure, return 404 or 403.
-        * 2) If file successfully opened, upload it to client.
-        * 3) If to forward request to appserver, perform the following:
-        *
-        * XXX Rewrite this
-        * 1) Verify if session cookie provided.  If not, invoke appserver
-        *    to create a new session and send new session cookie to client,
-        *    redirecting it to the same path after a few seconds.  Record
-        *    SID->appservfd but close connection to avoid creating too many
-        *    long connections for people providing invalid or no cookie.
-        *    This SID should be considered very temporary at this time and
-        *    we should ideally tell the appserver to destroy it if no
-        *    first request is made for it until some little time.
-        * 2) If we get a client cookie, verify that we know about it.
-        *    If not, proceed like for (1) again.  If necessary, reopen
-        *    link to appserver.  Then forward request to the server, and
-        *    send back results from it to the client.  Upon loss of a
-        *    connection, we can set again an expiry (although longer) for the
-        *    SID before asking appserv to destroy it...
-        * XXX Hmm actually to test if user supports cookies initially, we
-        * should probably simply send some temporary cookie so that we do not
-        * need to create a new SID unless we know client is likely to use it.
-        * Otherwise we would be creating a number of SIDs for nothing.
-        * Moreover, even for POST processing, which happens before, cookie
-        * must be existing.
-        */
-
-       if (!(appserv_match = this.http_vhost.host_appmatch(path.virtual))) {
-
-               fd = new FD();
-               try {
-                       fd.open(path.real, FD.O_RDONLY);
-                       st = fd.fstat();
-               } catch (x) {
-                       http_error(this, 404, 'Not Found',
-                           path.virtual + ' could not be found.');
-                       return PSTAT_CLOSE_SUCCESS;
-               }
-
-               /* Directory? */
-               if ((st.st_mode & FD.S_IFDIR) != 0) {
-                       var error = false;
-                       var redirect = true;
-
-                       /*
-                        * Refit URL to configured index,
-                        * check if under appserver path and if so process
-                        * accordingly, else check if there's a file under it.
-                        */
-                       try {
-                               fd.close();
-                       } catch (x) {}
-                       if (this.http_vhost.index.charAt(0) == '/') {
-                               /* Recompute since index is fullpath */
-                               if (!(path = this.http_vhost.htdocs_root.
-                                   valid_virtual(this.http_vhost.index)))
-                                       error = true;
-                       } else {
-                               /* Append index path and retry */
-                               path.real += '/' + this.http_vhost.index;
-                               path.virtual += '/' + this.http_vhost.index;
-                       }
-
-                       /*
-                        * Verify again if new index matches an appserv path
-                        */
-                       if (!error) {
-                               if (!(appserv_match = this.http_vhost.
-                                   host_appmatch(path.virtual))) {
-
-                                       /*
-                                        * Attempt to reopen static file.
-                                        * On success, close it and redirect
-                                        * client to it.
-                                        */
-                                       try {
-                                               fd.open(path.real,
-                                                   FD.O_RDONLY);
-                                               fd.close();
-                                               http_redirect(this,
-                                                   path.virtual);
-                                               return PSTAT_CLOSE_SUCCESS;
-                                       } catch (x) {
-                                               error = true;
-                                       }
-                               }
-                       }
-
-                       if (error) {
-                               http_error(this, 403, 'Permission Denied',
-                                   'You do not have the permission to ' +
-                                   'access the resource ' + path.virtual +
-                                   '.');
-                               return PSTAT_CLOSE_SUCCESS;
-                       } else
-                               this.http_path = path.virtual;
-               }
-       }
-
-       /*
-        * If under appserv path, make sure client supports HTTP cookies.
-        * We do this by verifying that we are able to obtain a "cookie=yes"
-        * cookie, without which we send one to the client redirecting to the
-        * same URL.
-        */
-       if (appserv_match && this.http_vars_cookies_count == 0) {
-               /* Ensure that client supports HTTP cookies */
-               doc = new HTTPReply(200, "OK",
-                   'text/html; charset=' + options.default_charset);
-               doc.addNoCacheHeaders();
-               doc.addHeader('Set-Cookie: cookies=yes; path=/');
-               doc.addContent('<html><head><META HTTP-EQUIV="refresh" ' +
-                   'CONTENT="5; URL=' + path.virtual + '"><title>Cookies' +
-                   '</title></head><body><h1>Cookies</h1><p>We are ' +
-                   ' verifying if your browser supports HTTP cookies.  ' +
-                   'These are required to keep persistent session data ' +
-                   'among your connections.  The destination page should ' +
-                   'load automatically in a few seconds.</p>' +
-                   ' <p>If it doesn\'t, please ensure that HTTP cookies ' +
-                   'are enabled on your HTTP client and are accepted ' +
-                   'from this server.</p>' +
-                   '<p>If the page still does not load properly after a ' +
-                   'few seconds, please click on <a href="' + path.virtual +
-                   '">this link</a>.</p><br><sub>' + SERVER_VERSION +
-                   '<br>' + SERVER_CVSID + '</sub></body></html>');
-               doc.flush(this, null);
-
-               return PSTAT_CLOSE_SUCCESS;
-       }
-
-       /* XXX */
-       if (appserv_match) {
-               http_error(this, 500, 'Internal Server Error',
-                   'You have requested an application server handled path ' +
-                   'which cannot be processed at this time.  Please try ' +
-                   'again later.');
-               return PSTAT_CLOSE_SUCCESS;
-       }
-
-       /*
-        * Only continue if file is a regular file
-        */
-       if (!appserv_match && (st.st_mode & FD.S_IFREG) == 0) {
-               fd.close();
-               http_error(this, 403, 'Permission Denied',
-                   'You do not have the permission to access the resource ' +
-                   path.virtual + '.');
-               return PSTAT_CLOSE_SUCCESS;
-       }
-
-       /*
-        * Extract file extension, as well as its mime type.
-        */
-       if ((i = path.virtual.lastIndexOf('.')) != -1) {
-               ext = (path.virtual.substr(i + 1)).toLowerCase();
-               if (ext.lastIndexOf('/') == -1 &&
-                   mimetypes_table[ext] != undefined)
-                       mimetype = mimetypes_table[ext];
-               else
-                       mimetype = options.default_mimetype;
-       }
-       /*
-        * Add charset to mime type
-        */
-       mimetype += '; charset=' + this.http_vhost.charset;
-
-       /*
-        * If client only wanted the document if it wasn't modified since
-        * a certain time, report that it wasn't if it is the case.
-        */
-       if (this.http_modified_since != undefined &&
-           st.st_mtime <= this.http_modified_since) {
-               fd.close();
-               res = new HTTPReply(304, 'Not Modified', null);
-               res.flush(this, null);
-               return PSTAT_CLOSE_SUCCESS;
-       }
-
-       /*
-        * If client only requested a range of bytes of the file, verify if
-        * the range is valid, and if so, arrange to only transfer the
-        * requested part of the file.
-        * In any other case, simply transfer the whole file.
-        */
-       if (this.http_range != undefined) {
-               var w;
-
-               if (this.http_range.startsWith('bytes'))
-                       this.http_range = this.http_range.substr(5);
-               if (this.http_range.length > 0 &&
-                   this.http_range.charAt(0) == '=')
-                       this.http_range = this.http_range.substr(1);
-               if ((w = this.http_range.split('-')).length == 2) {
-                       var from, to;
-
-                       if (w[0] == '')
-                               w[0] = 0;
-                       if (w[1] == '')
-                               w[1] = st.st_size - 1;
-                       from = Number(w[0]);
-                       to = Number(w[1]);
-
-                       if (from >= 0 && to < st.st_size && to >= from) {
-                               res = new HTTPReply(206, 'Partial Content',
-                                   mimetype);
-                               res.addHeader('Content-Range: bytes ' +
-                                   from + '-' + to + '/' + st.st_size);
-                               this.transfer_size = Math.abs((to - from) + 1);
-                               if (from > 0) {
-                                       try {
-                                               fd.lseek(from, FD.SEEK_SET);
-                                       } catch(x) {
-                                               stderr.write(x +
-                                                   " at lseek()\n");
-                                       }
-                               }
-                       }
-               }
-       }
-       if (res == undefined) {
-               res = new HTTPReply(200, 'OK', mimetype);
-               this.transfer_size = Math.abs(st.st_size);
-       }
-
-       /*
-        * Flush HTTP header, sending it
-        */
-       res.flush(this, this.transfer_size);
-
-       /*
-        * Switch to outbound transfer mode.
-        */
-       this.transfer_state = TSTATE_READ;
-       this.transfer_src = fd;
-       this.transfer_dst = this;
-       this.transfer_eof = false;
-       this.transfer_data = '';
-       this.state = state_http_transfer_file;
-       this.events = FD.POLLOUT;
-
-       /*
-        * Return with PSTAT_CONTINUE, to delegate operations to
-        * state_http_transfer_file().
-        */
-       return PSTAT_CONTINUE;
-}
-
-/*
- * Triggers a connection to an appserv if possible, queueing a new FD in the
- * event queue for asynchroneous connection.  state_connect_appserv() will
- * be called whenever the event occurs.  If connection is already established
- * to an appserv for this sid, sets appserv_fd and returns true immediately.
- * cfd and sid are passed in a matter for state_connect_appserv() to be able
- * to resume.  sid can be null if a new sid is to be created, or a sid to be
- * resumed.
- * Returns true on success or false on error.
- */
-FD.prototype.appserv_connect = function(sid, set)
-{
-       var s, fd;
-
-       /*
-        * SID already served by a current appserv connection?
-        */
-       if ((fd = sid_table[sid]) != undefined) {
-               this.appserv_fd = fd;
-               return true;
-       }
-
-       /*
-        * Allocate a new appserv slot
-        */
-       if ((s = this.vhost.server_get()) == undefined)
-               return false;
-
-       /*
-        * Create new appserv fd and initiate connection, delegating to
-        * state_connect_appserv()
-        */
-       try {
-               fd = new FD();
-               fd.type = STYPE_CONNECT;
-               fd.fcntl(FD.F_SETFL, FD.O_NONBLOCK);
-
-               fd.connect(s.host, s.port);
-               fd.events = FD.POLLOUT;
-               fd.state = state_connect_appserv;
-
-               fd.client_fd = this;
-               fd.sid = sid;
-               fd.set = set;
-               fd.appserv = s;
-
-               pollset.add(fd);
-       } catch (x) {
-               stderr.write(x + " in appserv_connect()\n");
-               return false;
-       }
-
-       return true;
-}
-
-/*
- * Once a non-blocking connect(2) has been called on a new socket, it is added
- * to the polling set with POLLOUT, which causes this function to be called to
- * attempt to complete or cancel the connection.
- * This function switches to the state_appserv_sid() on success, or causes
- * the connection to be closed on error.
- */
-function state_connect_appserv(time)
-{
-
-       if (this.getsockopt(FD.SO_ERROR) != 0) {
-               /*
-                * Error.  Close appserv fd, removing it from the polling set
-                * and send error to corresponding client fd.
-                */
-               try {
-                       this.close();
-               } catch (x) {};
-               /*
-                * XXX Hmm this appears ridiculous.
-                * We ideally shouldn't care about the http client fd here,
-                * but instead the client fd should remain in a state to
-                * continue processing once the sid it awaits for is being
-                * served by an appserv connection.  It also should get status
-                * via the same system, so that it may return an error
-                * instead in response to the client request.
-                * Possibly that instead of only POLL* events, we could also
-                * have other types of internal events?  This would still
-                * expect poll to return regularily, though.  Maybe that we
-                * just need a state that does nothing until response is
-                * obtained, and a way for this system to "notify" that fd?
-                * Then we still need the client_fd, though.
-                * Hmm... interestingly we could mute the client fd from poll
-                * events setting events to 0, and put it back to POLLOUT
-                * causing the state function to be called again whenever it
-                * makes sense to.  This would prevent the main loop from
-                * being clobbered by dummy POLLOUT events for nothing while
-                * the client fd waits for an appserv connection to be
-                * established.  Remains to see if we need to awake multiple
-                * pending requests at the same time...  Then those requests
-                * must also be paused whenever a connection is attempted for
-                * a particular sid, too, using a table for lookup.
-                * say... sid_connecting{} containing objects such as <sid>
-                * indexed arrays, holding a list of client FD objects which
-                * are queued waiting for an appserv to be available for that
-                * sid.
-                * XXX Then we have another potential problem: multiple
-                * concurrent http client requests must be able to query the
-                * appserv, in which case they should be serialized.  In a
-                * similar manner, we would need to block those until they can
-                * gain right to send a query, which case that particular fd
-                * must also be blocked until answer or appserv disconnection
-                * takes place.
-                * Hence we seem to need some general purpose FD based
-                * semaphore system...
-                * XXX Let's resume this...  we need states:
-                * WAIT_CONNECTION (per-sid, must also have create/load
-                * command and if create, be able to return to client the
-                * new SID)
-                * WAIT_SID (per-client)
-                * TRANSFER_SID (one client at a time)
-                */
-               http_error(this.client_fd, 500, 'Internal Server Error',
-                   'There was an error establishing connection to an ' +
-                   'application server.  Please try again later.');
-               this.client_fd.state = state_close_success;
-               this.client_fd.events = FD.POLLOUT;
-               /*
-               this.set[this.index] = undefined;
-               this.vhost.server_put(this.appserv);
-               this.appserv = undefined;
-               */
-               return PSTAT_CLOSE_ERROR;
-       }
-
-       /* Success */
-       this.type = STYPE_APPSERV;
-       this.client_fd = undefined;
-       this.transfer_state = TSTATE_WRITE;
-       /* XXX */
-
-       return PSTAT_CONTINUE;
-}
-
-/*
- * Upon successful connection, a switch to this state is made.
- * This sends the initial sid creation or loading/resuming request to the
- * server and closes on error, or sets up the sid->fd relationship on success
- * for client requests to be handled through that fd for that sid later on.
- */
-function state_appserv_sid(time)
-{
-       var data;
-
-       if (this.transfer_state == TSTATE_WRITE) {
-       } else { /* TSTATE_READ */
-               while ((data = this.breadline(256, false)) != null) {
-               }
-               if (data == null) {
-                       /* Error */
-               }
-       }
-}
-
-/*
- * Dummy function allowing to cause a wanted fd from the set to be closed.
- */
-function state_close_success(time)
-{
-
-       return PSTAT_CLOSE_SUCCESS;
-}
-
-
-FD.prototype.httpDebug = function()
-{
-       var table, tr, td, pre, font;
-
-       table = new MLTag('table', true);
-       table.addAttr('width', '100%');
-       table.addAttr('border', '1');
-
-       tr = new MLTag('tr', true);
-       td = new MLTag('td', true);
-       td.addAttr('width', '10%');
-       td.addAttr('align', 'right');
-       td.addContent('You are:');
-       tr.addContent(td);
-       td = new MLTag('td', true);
-       td.addAttr('width', '90%');
-       td.addContent(this.client_addr + ':' + this.client_port);
-       tr.addContent(td);
-       table.addContent(tr);
-
-       try {
-               tr = new MLTag('tr', true);
-               td = new MLTag('td', true);
-               td.addAttr('align', 'right');
-               td.addContent('You sent:');
-               tr.addContent(td);
-               td = new MLTag('td', true);
-               font = new MLTag('font', true);
-               font.addAttr('size', '-3');
-               pre = new MLTag('pre', true);
-               pre.addContent(this.query_data.toSource());
-               font.addContent(pre);
-               td.addContent(font);
-               tr.addContent(td);
-               table.addContent(tr);
-       } catch (x) {}
-
-       try {
-               tr = new MLTag('tr', true);
-               td = new MLTag('td', true);
-               td.addAttr('align', 'right');
-               td.addContent('GET vars:');
-               tr.addContent(td);
-               td = new MLTag('td', true);
-               font = new MLTag('font', true);
-               font.addAttr('size', '-3');
-               pre = new MLTag('pre', true);
-               pre.addContent(this.http_vars_get.toSource());
-               font.addContent(pre);
-               td.addContent(font);
-               tr.addContent(td);
-               table.addContent(tr);
-       } catch (x) {}
-
-       try {
-               tr = new MLTag('tr', true);
-               td = new MLTag('td', true);
-               td.addAttr('align', 'right');
-               td.addContent('POST vars:');
-               tr.addContent(td);
-               td = new MLTag('td', true);
-               font = new MLTag('font', true);
-               font.addAttr('size', '-3');
-               pre = new MLTag('pre', true);
-               pre.addContent(this.http_vars_post.toSource());
-               font.addContent(pre);
-               td.addContent(font);
-               tr.addContent(td);
-               table.addContent(tr);
-       } catch (x) {}
-
-       try {
-               tr = new MLTag('tr', true);
-               td = new MLTag('td', true);
-               td.addAttr('align', 'right');
-               td.addContent('Cookies:');
-               tr.addContent(td);
-               td = new MLTag('td', true);
-               font = new MLTag('font', true);
-               font.addAttr('size', '-3');
-               pre = new MLTag('pre', true);
-               pre.addContent(this.http_vars_cookies.toSource());
-               font.addContent(pre);
-               td.addContent(font);
-               tr.addContent(td);
-               table.addContent(tr);
-       } catch (x) {}
-
-       try {
-               tr = new MLTag('tr', true);
-               td = new MLTag('td', true);
-               td.addAttr('align', 'right');
-               td.addContent('VHost:');
-               tr.addContent(td);
-               td = new MLTag('td', true);
-               td.addContent(this.http_vhost.name);
-               tr.addContent(td);
-               table.addContent(tr);
-       } catch (x) {}
-
-       try {
-               tr = new MLTag('tr', true);
-               td = new MLTag('td', true);
-               td.addAttr('align', 'right');
-               td.addContent('Path:');
-               tr.addContent(td);
-               td = new MLTag('td', true);
-               td.addContent(this.http_path);
-               tr.addContent(td);
-               table.addContent(tr);
-       } catch (x) {}
-
-       try {
-               tr = new MLTag('tr', true);
-               td = new MLTag('td', true);
-               td.addAttr('align', 'right');
-               td.addContent('Mod-Since:');
-               tr.addContent(td);
-               td = new MLTag('td', true);
-               td.addContent(this.http_modified_since);
-               tr.addContent(td);
-               table.addContent(tr);
-       } catch (x) {}
-
-       try {
-               tr = new MLTag('tr', true);
-               td = new MLTag('td', true);
-               td.addAttr('align', 'right');
-               td.addContent('SessID:');
-               tr.addContent(td);
-               td = new MLTag('td', true);
-               td.addContent(this.http_sessid);
-               tr.addContent(td);
-               table.addContent(tr);
-       } catch (x) {}
-
-       return table.toStr(0);
-}
-
-/*
- * Verifies if property name ends with [], which considers it as an array of
- * values which are then pushed into that array.
- * Sets the property normally otherwise.
- * XXX We probably need additional parsing here, i.e. to replace %<nn>
- */
-function property_add(obj, prop, val)
-{
-       prop = unescape(prop.replace(/\+/g, ' '));
-       val = unescape(val.replace(/\+/g, ' '));
-
-       if (prop.endsWith('[]')) {
-               /* Array entry */
-               prop = prop.substring(0, prop.length - 2);
-               if (obj[prop] == undefined)
-                       obj[prop] = [];
-               obj[prop].push(val);
-       } else
-               obj[prop] = val;
-}
-
-
-
-/*
- * Connections limits management
- */
-
-function CLimits(maxtotal, maxaddr)
-{
-       this.connections = 0;
-       this.addresses = {};
-       this.maxtotal = maxtotal;
-       this.maxaddr = maxaddr;
-}
-
-CLimits.prototype = {
-       add: function(fd)
-       {
-               var addr, addrcnt;
-
-               if (this.connections >= this.maxtotal)
-                       return false;
-
-               addr = fd.client_addr;
-               if ((addrcnt = this.addresses[addr]) != undefined &&
-                   addrcnt >= this.maxaddr)
-                       return false;
-
-               if (addrcnt == undefined)
-                       addrcnt = 1;
-               else
-                       addrcnt++;
-               this.addresses[addr] = addrcnt;
-               this.connections++;
-
-               return true;
-       },
-
-       remove: function(fd)
-       {
-               var addr;
-
-               addr = fd.client_addr;
-               if ((--this.addresses[addr]) == 0)
-                       delete this.addresses[addr];
-
-               this.connections--;
-       }
-};
-
-var climits = new CLimits();
-
-
-
-/*
- * Descriptor polling set management
- */
-
-function PollSet()
-{
-       this.count = 0;
-       this.min = 0;
-       this.set = {};
-}
-
-PollSet.prototype = {
-       add: function(fd)
-       {
-
-               if (this.count > 9999999)
-                       this.count = this.min + 1;
-               fd.fdidx = this.count++;
-               this.set[fd.fdidx] = fd;
-       },
-
-       remove: function(fd)
-       {
-
-               delete this.set[fd.fdidx];
-       }
-};
-
-var pollset = new PollSet();
-
-
-
-/*
- * Main program
- */
-function main() {
-       var i;
-       /*
-       var sess_gc_secs = 0;
-       */
-       var fd, e, efd, flush;
-
-       http_log_init();
-
-       /*
-        * Populate vhosts database
-        */
-       for (i in vhosts) {
-               try {
-                       var v = new VHost(vhosts[i]);
-               } catch (x) {
-                       stderr.write(x + " creating VHost object\n");
-               }
-       }
-       /*
-        * Attempt to link default_vhost to a VHost object
-        */
-       if (options.default_vhost == undefined) {
-               stderr.write("No default_vhost property in options, exiting\n");
-               exit();
-       }
-       if (vhosts_table[options.default_vhost.toLowerCase()] != undefined)
-               default_vhost =
-                   vhosts_table[options.default_vhost.toLowerCase()];
-       else {
-               stderr.write('Default vhost ' + options.default_vhost +
-                   " unkonwn, exiting\n");
-               exit();
-       }
-
-       /*
-        * Populate mimetypes database.
-        * XXX If this got very large, because the destination strings
-        * are rather large, it might be good to use indexes or references
-        * to them rather than provide the string for each extension.
-        */
-       for (i in mimetypes) {
-               var i2, ext;
-
-               for (i2 in mimetypes[i]) {
-                       ext = mimetypes[i][i2].toLowerCase();
-                       if (mimetypes_table[ext] != undefined) {
-                               stderr.write('Conflicting mime type ' +
-                                   ext + ' -> ' + i + "\n");
-                               continue;
-                       }
-                       mimetypes_table[ext] = i;
-               }
-       }
-
-       /*
-        * Add debugging port XXX Make this optional and allow to specify
-        * address and port number
-        */
-       /*
-       try {
-               fd = new FD();
-               fd.socket(FD.AF_INET, FD.SOCK_STREAM, 0);
-               fd.bind('127.0.0.1', 8199);
-               fd.setsockopt(FD.SO_REUSEADDR, 1);
-               fd.fcntl(FD.F_SETFL, FD.O_NONBLOCK);
-               fd.listen(0);
-               fd.events = FD.POLLIN;
-               fd.type = STYPE_LDEBUG;
-               pollset.add(fd);
-       } catch (x) {
-                       stderr.write(x + " preparing debugging socket\n");
-       }
-       */
-
-       /*
-        * Initialize server
-        */
-       for (i in listen) {
-               try {
-                       fd = new FD();
-                       fd.socket(FD.AF_INET, FD.SOCK_STREAM, 0);
-                       fd.bind(listen[i].address, listen[i].port);
-
-                       fd.setsockopt(FD.SO_REUSEADDR, 1);
-                       fd.setsockopt(FD.SO_LINGER, -1);
-                       fd.setsockopt(FD.SO_KEEPALIVE, 1);
-                       fd.setsockopt(FD.TCP_NODELAY, 1);
-
-                       fd.fcntl(FD.F_SETFL, FD.O_NONBLOCK);
-                       fd.listen(options.max_connections);
-                       /*
-                        * Mark socket as bound one and add it to
-                        * polling set
-                        */
-                       fd.events = FD.POLLIN;
-                       fd.type = STYPE_LISTEN;
-                       pollset.add(fd);
-               } catch (x) {
-                       stderr.write(x + " preparing listening socket\n");
-               }
-       }
-       if (pollset.count == 0)
-               exit();
-
-       /*
-        * Reset pollset.min to avoid overwriting static descriptors
-        */
-       pollset.min = pollset.count;
-
-       /*
-        * Main loop
-        */
-       for (;;) {
-               /*
-                * Determine next to expire FD event, so that we can sleep
-                * as long as possible.  Also get rid of expired requests.
-                * XXX Could be in a function
-                */
-               var cur = Date.parse(new Date) / 1000;
-               var exp = cur + 3600;
-               var old;
-
-               for (i in pollset.set) {
-                       if ((fd = pollset.set[i]) == undefined ||
-                           fd.type != STYPE_HTTP)
-                               continue;
-                       if (fd.expires <= cur) {
-                               /*
-                                * Request timeout expired for this
-                                * descriptor, we must close it.
-                                */
-                               fd.close();
-                               climits.remove(fd);
-                               pollset.remove(fd);
-                               continue;
-                       }
-                       if (fd.expires < exp)
-                               exp = fd.expires;
-               }
-               exp -= cur;
-
-               /*
-                * Poll our set of descriptors for events.
-                * XXX We definitely should use libevent here.
-                * The polling set gets regenerated by the C code at every
-                * call, which is suboptimal.  I guess that we still could use
-                * poll while providing C primitives to add/remove descriptors
-                * from the set a-la select(2).  But libevent(3) is always
-                * superior while being able to run on various systems unlike
-                * BSD kqueue(2).
-                */
-               try {
-                       e = FD.poll(pollset.set, exp * 1000);
-               } catch (x) {
-                       stderr.write(x + " for poll(2)\n");
-                       continue;
-               }
-
-               /*
-                * Verify if a timeout occurred.  Because our poll
-                * implementation returns an array, its timeout event can be
-                * checked against by verifying if the set is empty.
-                */
-               if (e.length == 0) {
-                       /* Timeout */
-                       continue;
-               }
-
-               /*
-                * XXX We should perhaps check timeouts after, so that we
-                * only need to query time once per loop?
-                * We could only do this if we knew that all our next
-                * processing is non-blocking, however.  Otherwise we
-                * would loose track of actual time.
-                */
-               old = cur;
-               cur = (Date.parse(new Date) / 1000);
-
-               /*
-                * Verify if we should call the session gc, and if so, do so.
-                * XXX We probably shouldn't do this anymore
-                */
-               /*
-               sess_gc_secs += cur - old;
-               if (sess_gc_secs >= options.sess_gc_interval) {
-                       sess_gc_secs = 0;
-                       session_gc(cur);
-               }
-               */
-
-               /*
-                * Run through set of descriptors with pending events
-                */
-               for (i in e) {
-                       if (e[i] == undefined)
-                               continue;
-                       efd = e[i];
-
-                       /* XXX Make this optional */
-                       /*
-                       if (efd.type == STYPE_LDEBUG &&
-                           (efd.revents & FD.POLLIN) != 0) {
-                               try {
-                                       fd = efd.accept();
-                                       fd.type = STYPE_DEBUG;
-                                       fd.state = state_debug_read;
-                                       pollset.add(fd);
-                               } catch (x) {
-                                       stderr.write(x + " at accept(2)\n");
-                                       fd.close();
-                               }
-                               continue;
-                       }
-                       if (efd.type == STYPE_DEBUG) {
-                               if ((efd.revents & (FD.POLLHUP | FD.POLLERR))
-                                   != 0)
-                                       efd.stat = PSTAT_CLOSE_ERROR;
-                               if (efd.stat == PSTAT_CONTINUE &&
-                                   (efd.revents & (FD.POLLIN | FD.POLLOUT))
-                                   != 0) {
-                                       try {
-                                               efd.stat = efd.state(cur);
-                                       } catch (x) {
-                                               efd.stat == PSTAT_CLOSE_ERROR;
-                                       }
-                               }
-                               if (efd.stat == PSTAT_CONTINUE)
-                                       continue;
-                               try {
-                                       efd.close();
-                               } catch (x) {}
-                               pollset.remove(efd);
-                               continue;
-                       }
-                       */
-
-                       /*
-                        * If descriptor is a bound one, attempt to accept
-                        * the new client connection
-                        */
-                       if (efd.type == STYPE_LISTEN &&
-                           (efd.revents & FD.POLLIN) != 0) {
-                               try {
-                                       fd = efd.accept();
-                                       if (!climits.add(fd)) {
-                                               http_error(fd, 403.9,
-                                                   'Too Many Connections',
-                                   'Your browser has exceeded its maximum ' +
-                                   'allowed number of concurrent ' +
-                                   'connections.');
-                                               fd.close();
-                                               continue;
-                                       }
-                                       /*
-                                        * Setup client's initial state and
-                                        * add FD to polling set
-                                        */
-                                       fd.state_http_init(cur);
-                                       pollset.add(fd);
-                               } catch (x) {
-                                       stderr.write(x + " at accept(2)\n");
-                                       fd.close();
-                               }
-                               continue;
-                       }
-
-                       /*
-                        * Most of the code for STYPE_HTTP and STYPE_APPSERV
-                        * is shared.  STYPE_CONNECT is transitional and
-                        * handled as other events.
-                        */
-
-                       /*
-                        * Close connection on error conditions,
-                        * Call the FD's state function on interesting
-                        * events, which will tell when we should drop the
-                        * client.
-                        */
-                       if ((efd.revents & (FD.POLLHUP | FD.POLLERR)) != 0 ||
-                           /* XXX poll(2) says POLLOUT | POLLHUP impossible */
-                           ((efd.events & FD.POLLOUT) == 1 &&
-                           (efd.revents & FD.POLLIN) == 1))
-                               efd.stat = PSTAT_CLOSE_ERROR;
-                       else if (efd.stat != PSTAT_CLOSE_ERROR &&
-                           (efd.revents & (FD.POLLIN | FD.POLLOUT)) != 0) {
-                               /*
-                                * Flush output queue if any and possible,
-                                * since we're in non-blocking mode, writes
-                                * can yield short counts.
-                                * If PSTAT_CLOSE_SUCCESS, we must not
-                                * close until we flushed everything, but
-                                * immediately close once we do.
-                                * Otherwise, on PSTAT_CLOSE_ERROR,
-                                * we must close immediately without flushing.
-                                */
-                               if ((flush = efd.bflushw(false)) == -1)
-                                       efd.stat = PSTAT_CLOSE_ERROR;
-                               else if (flush == 0 &&
-                                   efd.stat == PSTAT_CONTINUE)
-                                       efd.stat = efd.state(cur);
-                               else if (flush == 1 &&
-                                   efd.stat != PSTAT_CLOSE_ERROR)
-                                       continue;
-                       }
-
-                       if (efd.stat != PSTAT_CONTINUE) {
-                               try {
-                                       /*
-                                        * XXX This is our closing point,
-                                        * where we actually should log.
-                                        */
-                                       efd.close();
-                               } catch (x) {}
-                               if (efd.type == STYPE_APPSERV) {
-                                       /* Dismiss SID->FD table entry */
-                                       sid_table[efd.sid] = undefined;
-                                       /* appserv object back to pool */
-                                       efd.vhost.server_put(efd.appserv);
-                                       efd.appserv = undefined;
-                                       /*
-                                        * XXX Unlock any waiters and cause
-                                        * them to return a 500 error
-                                        */
-                               }
-                               /*
-                                * If there were any static file uploads in
-                                * progress, close source file's descriptor
-                                */
-                               if (efd.transfer_src != undefined) {
-                                       try {
-                                               efd.transfer_src.close();
-                                       } catch (x) {}
-                               }
-                               climits.remove(efd);
-                               pollset.remove(efd);
-                       }
-               }
-       }
-
-       /* NOTREACHED */
-       err.close();
-}
-
-main();
-/* NOTREACHED */
-exit(0);
diff --git a/mmsoftware/js/js-sh/app/httpd/options.js b/mmsoftware/js/js-sh/app/httpd/options.js
deleted file mode 100644 (file)
index 2091160..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/* $Id: options.js,v 1.27 2006/11/16 06:59:18 mmondor Exp $ */
-
-var ilibprefix = "/home/mmondor/work/mmondor/mmsoftware/js/jslib/";
-
-/* Global options */
-var options = {
-       debug:                  true,
-       max_connections:        64,
-       max_connections_addr:   8,      /* 8 minimum recommended */
-       max_query_size:         4096,
-       max_post_size:          65535,
-       io_timeout:             60,
-       file_buf_size:          65535,
-       default_vhost:          "appserv.pulsar-zone.net",
-       default_mimetype:       "application/octet-stream",
-       default_charset:        "us-ascii",
-       default_index:          "index.html",
-       ban_msie:               false,
-       ban_windows:            false
-};
-
-/* Address:port combinations to listen to */
-var listen = [
-       {
-               address:        "127.0.0.1",
-               port:           8180
-       },
-       {
-               address:        "192.168.1.10",
-               port:           8180
-       }
-];
-
-/* Simple mapping from appserv application name to port number it runs on */
-var ap = {
-       "test":                 8100,
-};
-
-/* Configuration for each vhost, options may override global options */
-var vhosts = [
-       /* Default virtual host */
-       {
-               name:           "appserv.pulsar-zone.net",
-               aliases: [
-                               "appserv.ginseng.xisop"
-               ],
-               root:           "/home/data/jshttpd/appserv",
-               index:          "/app/index",
-               appserv: {
-                       paths_cache_max: 64,
-                       /* URL patterns redirected to js-appserv (regexp) */
-                       paths: [
-                               "^/app/"
-                       ],
-                       /* Where to connect to js-appserv(s) */
-                       /* If more than one, load balancing is done */
-                       servers: [
-                               {
-                                       host:           "localhost",
-                                       port:           ap['test'],
-                                       clients:        64
-                               }
-                               /*
-                               {
-                                       host:           "ginseng.xisop",
-                                       port:           ap['test'],
-                                       clients:        64
-                               }
-                               */
-                       ]
-               },
-               charset:        "iso-8859-1"
-       },
-       {
-               name:           "mmondor.pulsar-zone.net",
-               aliases: [
-                               "mmondor.ginseng.xisop"
-               ],
-               root:           "/home/data/jshttpd/mmondor",
-               charset:        "iso-8859-1"
-       }
-];
-
-/* Static definitions of file type -> mime type description */
-var mimetypes  = {
-       "text/html":                            [ "html", "htm", "dhtml" ],
-       "text/plain":                           [ "txt" ],
-       "text/css":                             [ "css" ],
-       "application/x-xpinstall":              [ "xpi" ],
-       "application/vnd.mozilla.xul+xml":      [ "xul" ],
-       "text/rdf":                             [ "rdf" ],
-       "application/pdf":                      [ "pdf" ],
-       "application/postscript":               [ "ps" ],
-       "application/x-tar":                    [ "tar" ],
-       "application/x-gzip":                   [ "gz" ],
-       "application/x-bzip2":                  [ "bz2" ],
-       "application/zip":                      [ "zip" ],
-       "application/x-javascript":             [ "js" ],
-       "application/x-c":                      [ "c", "h", "cpp", "cc" ],
-       "application/x-sh":                     [ "sh" ],
-       "application/x-shockwave-flash":        [ "swf" ],
-       "application/xml":                      [ "xml" ],
-       "application/xml-dtd":                  [ "dtd" ],
-       "image/jpg":                            [ "jpg", "jpeg" ],
-       "image/png":                            [ "png" ],
-       "image/gif":                            [ "gif" ],
-       "image/x-icon":                         [ "ico" ],
-       "image/svg+xml":                        [ "svg" ],
-       "video/mpeg":                           [ "mpeg", "mpg" ],
-       "video/quicktime":                      [ "mov" ],
-       "video/x-msvideo":                      [ "asf", "asx", "wmv", "avi" ]
-};
diff --git a/mmsoftware/js/js-sh/app/irclog/config.js b/mmsoftware/js/js-sh/app/irclog/config.js
deleted file mode 100644 (file)
index e340b69..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* $Id: config.js,v 1.4 2006/11/27 15:18:17 mmondor Exp $ */
-
-/* Configuration */
-var irc_channel = '#gurumeditation';
-var irc_servers = [
-       'irc.freenode.net:6667'
-       /*
-       'ginseng.xisop:6667',
-       'mudbug.org:6667'
-       */
-];
-var irc_nicknames = [
-       'nanobit',
-       'e-chemical',
-       'e-alchemy',
-       'nick_',
-       'nick__'
-];
-var irc_user = 'nanobit', irc_name = 'e-chemical e-alchemy';
-var irc_reconnect_delay = 10;
-
-var irc_op_passwd = 'somepassword';
-var irc_voice_passwd = 'somepassword';
-var irc_quit_passwd = 'somepassword';
-var irc_msg_passwd = 'somepassword';
-var irc_ban_passwd = 'somepassword';
-
-var irc_part_message = 'Farewell';
-var irc_quit_message = 'Farewell';
-var irc_auto_whois = true;
-var irc_log_pings = false;
-var irc_auto_voice = [];
-var irc_auto_op = [
-       "^mur![^@]*@smtp.uiah.fi$",
-       "^phadthai![^@]*@ginseng.pulsar-zone.net$",
-       "^cprior![^@]*@unaffiliated/cprior$",
-       "^Kool-Aid![^@]*@[^.]*.[^.]*.or.comcast.net$"
-];
-var irc_auto_ban = [];
-
-/* XXX Would be more complex, but ideal
-var networks = [
-       {
-               name: "rubiks",
-               channels: [
-                       "#test"
-               ],
-               servers: [
-                       "ginseng.xisop:6667"
-               ]
-       }
-];
-*/
diff --git a/mmsoftware/js/js-sh/app/irclog/irclog.js b/mmsoftware/js/js-sh/app/irclog/irclog.js
deleted file mode 100644 (file)
index 897d2d4..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-/* $Id: irclog.js,v 1.14 2006/11/30 18:32:48 mmondor Exp $ */
-
-var irc_version = '$Id: irclog.js,v 1.14 2006/11/30 18:32:48 mmondor Exp $';
-
-function file_read(name)
-{
-       var fh;
-       var data = '';
-
-       try {
-               fh = new File(name, 'r');
-       } catch (x) {
-               stderr.write('file_read() - open: ' + x + "\n");
-               return null;
-       }
-
-       try {
-               for (;;)
-                       data += fh.read(1, 16384);
-       } catch (x) {
-               if (!fh.eof()) {
-                       stderr.write('file_read() - read: ' + x + "\n");
-                       data = null;
-               }
-       }
-       fh.close();
-
-       return data;
-}
-
-eval (file_read('config.js'));
-
-
-
-/* XXX Hahaha the ugly hack!  I need to write a Timer class... */
-function sleep(seconds)
-{
-       try {
-               var fh = File.popen('/bin/sleep ' + seconds, 'r');
-               try {
-                       for (;;)
-                               fh.read(256);
-               } catch (x) {}
-               fh.close();
-       } catch (x) { stderr.write(x + "\n"); }
-}
-
-/*
- * Returns an object with the address and port of a server to (re)connect to.
- * Uses round-robin among the specified servers array.  We also sleep during
- * a few seconds to prevent connect-flooding.
- */
-var last_server = 0;
-function select_server()
-{
-       var w = irc_servers[last_server++].split(':');
-
-       if (last_server == irc_servers.length)
-               last_server = 0;
-       if (w[1] == undefined)
-               w[1] = 6667;
-       else
-               w[1] = Number(w[1]);
-
-       last_nickname = 0;
-
-       return { address: w[0], port: w[1] };
-}
-
-var last_nickname = 0;
-function select_nickname()
-{
-       var s = irc_nicknames[last_nickname++];
-
-       if (last_nickname == irc_nicknames.length)
-               last_nickname = 0;
-
-       irc_nickname = s;
-       return s;
-}
-
-function log_init()
-{
-       var i;
-
-       log_digits = [];
-       for (i = 0; i < 60; i++) {
-               if (i < 10)
-                       log_digits[i] = '0' + i;
-               else
-                       log_digits[i] = i.toString();
-       }
-
-       stdout.setvbuf(File._IOLBF, 0);
-}
-
-function log_timestamp()
-{
-       var t = new Date();
-       var s = t.getUTCFullYear() + log_digits[t.getUTCMonth()] +
-           log_digits[t.getUTCDate()] + log_digits[t.getUTCHours()] +
-           log_digits[t.getUTCMinutes()] + log_digits[t.getUTCSeconds()] +
-           '-0000';
-
-       return s;
-}
-
-File.prototype.getline = function()
-{
-       var line = this.gets(1024, true);
-
-       /* Specifying false to gets() should strip these, but it's broken */
-       line = line.substr(0, line.length - 2);
-
-       if (!irc_log_pings && line.match(/^PING :/) != null)
-               return line;
-
-       /* Log input line as-is with timestamp immediately */
-       stdout.write(log_timestamp() + ' < ' + line + "\n");
-
-       return line;
-}
-
-File.prototype.putline = function(line)
-{
-       if (!irc_log_pings && line.match(/^PONG :/) != null) {
-               this.write(line + "\r\n");
-               return;
-       }
-
-       stdout.write(log_timestamp() + ' > ' + line + "\n");
-       this.write(line + "\r\n");
-}
-
-File.prototype.state_all = function(line)
-{
-       var s, w, from, to, msg;
-
-       /* PING :<server> */
-       if (line.match(/^PING :/) != null) {
-               this.putline('PONG ' + line.substr(5));
-               return true;
-       }
-
-       /* :<nick>!<user>@<host> PRIVMSG <to> :<message> */
-       if ((s = line.match(/^:[^\b!:]*![^\b@:]*@[^\b:]* PRIVMSG [^\b:]* :/))
-           != null) {
-               s = s.toString();
-               msg = line.substr(s.length);
-               from = line.substr(1, line.indexOf('!') - 1);
-               w = line.split(' ');
-               to = w[2];
-               if (msg.charCodeAt(0) == 0x01 &&
-                   msg.charCodeAt(msg.length - 1) == 0x01) {
-                       /* CTCP */
-                       msg = msg.substr(1, msg.length - 2);
-                       if (msg.match(/^PING [0-9]* [0-9]*$/) != null)
-                               this.putline('NOTICE ' + from + " :\001" +
-                                   msg + "\001");
-                       else if (msg == 'VERSION')
-                               this.putline('NOTICE ' + from + " :\001" +
-                                   'VERSION ' + irc_version + "\001");
-                       else if (msg == 'TIME')
-                               this.putline('NOTICE ' + from + " :\001" +
-                                   'TIME ' + (new Date()).toUTCString() +
-                                   "\001");
-                       return true;
-               }
-       }
-
-       return false;
-}
-
-File.prototype.state_nick = function()
-{
-       var line, w;
-
-       stdout.write(log_timestamp() + ' -+- Entering state_nick()' + "\n");
-
-       this.putline('NICK ' + select_nickname());
-       for (;;) {
-               line = this.getline();
-
-               if (this.state_all(line))
-                       continue;
-
-               /* :<server> 433 * <nick> :Nick already used */
-               if (line.match(/^:[^\b:]* 433 * [^\b:]* :/) != null) {
-                       this.putline('NICK ' + select_nickname());
-                       continue;
-               }
-
-               /* :<server> 376 <nick> :End of MOTD */
-               if (line.match(/^:[^\b:]* 376 [^\b:]* :/) != null)
-                       break;
-       }
-
-       this.state = File.prototype.state_log;
-       return true;
-}
-
-File.prototype.state_log = function()
-{
-       var line, s, from, to, chan, msg, w, i;
-
-       stdout.write(log_timestamp() + ' -+- Entering state_log()' + "\n");
-
-       for (;;) {
-               if (!on_channel) {
-                       sleep(++join_attempts);
-                       if (join_attempts > 10)
-                               join_attempts = 10;
-                       this.putline('JOIN ' + irc_channel);
-               }
-
-               line = this.getline();
-
-               if (this.state_all(line))
-                       continue;
-
-               /*
-                * XXX
-                * Ideally, for more security, we should detect JOIN and PART
-                * events which are for us but which we did not trigger.
-                * For instance, we want to leave automatically channels
-                * which an oper might have forced us into.  Similarily,
-                * we want to rejoin in case of an unexpected PART event from
-                * our part.  Moreover, it would be nice to also auto-detect
-                * further nickname changes applied to us automatically so
-                * that we may return to the nick state.
-                */
-
-               /* :<nick>!<user>@<host> JOIN :<channel> */
-               if ((s = line.match(/^:[^\b!:]*![^\b@:]*@[^\b:]* JOIN :/))
-                   != null) {
-                       s = s.toString();
-                       msg = line.substr(s.length);
-                       from = line.substr(1, line.indexOf('!') - 1);
-                       if (from.toLowerCase() == irc_nickname.toLowerCase() &&
-                           msg.toLowerCase() == irc_channel.toLowerCase())
-                               on_channel = true;
-                       else {
-                               if (irc_auto_whois)
-                                       this.putline('WHOIS ' + from);
-                               /* Check for auto op/voice/ban */
-                               w = line.split(' ');
-                               s = w[0].substr(1);
-                               for (i in irc_auto_voice) {
-                                       if (s.match(irc_auto_voice[i])
-                                           != null) {
-                                               this.putline('MODE ' +
-                                                   irc_channel + ' +v ' +
-                                                   from);
-                                               break;
-                                       }
-                               }
-                               for (i in irc_auto_op) {
-                                       if (s.match(irc_auto_op[i])
-                                           != null) {
-                                               this.putline('MODE ' +
-                                                   irc_channel + ' +o ' +
-                                                   from);
-                                               break;
-                                       }
-                               }
-                               for (i in irc_auto_ban) {
-                                       if (s.match(irc_auto_ban[i].regex)
-                                           != null) {
-                                               this.putline('MODE ' +
-                                                   irc_channel + ' +b ' +
-                                                   irc_auto_ban[i].mask);
-                                               this.putline('KICK ' +
-                                                   irc_channel + ' ' +
-                                                   from + ' :automatic ban');
-                                               break;
-                                       }
-                               }
-                       }
-                       continue;
-               }
-
-               /* :<nick>!<user>@<host> KICK <channel> <nick> :<message> */
-               if (line.match(
-                   /^:[^\b!:]*![^\b@:]*@[^\b:]* KICK [^\b:]* [^\b:]* :/)
-                   != null) {
-                       w = line.split(' ');
-                       chan = w[2];
-                       to = w[3];
-                       if (chan.toLowerCase() == irc_channel.toLowerCase() &&
-                           to.toLowerCase() == irc_nickname.toLowerCase()) {
-                               on_channel = false;
-                               join_attempts = 10;
-                               continue;
-                       }
-               }
-
-               /* :<nick>!<user>@<host> PRIVMSG <to> :<message> */
-               if ((s = line.match(
-                   /^:[^\b!:]*![^\b@:]*@[^\b:]* PRIVMSG [^\b:]* :/))
-                   != null) {
-                       s = s.toString();
-                       msg = line.substr(s.length);
-                       from = line.substr(1, line.indexOf('!') - 1);
-                       w = line.split(' ');
-                       to = w[2];
-                       if (to.toLowerCase() == irc_nickname.toLowerCase()) {
-                               if (on_channel &&
-                                   msg.match(/^!OP [^\b]* [^\b]*$/) != null) {
-                                       w = msg.split(' ');
-                                       if (w[1] == irc_op_passwd)
-                                               this.putline('MODE ' +
-                                                   irc_channel + ' +o ' +
-                                                   w[2]);
-                                       continue;
-                               } else if (on_channel &&
-                                   msg.match(/^!DEOP [^\b]* [^\b]*$/)
-                                   != null) {
-                                       w = msg.split(' ');
-                                       if (w[1] == irc_op_passwd)
-                                               this.putline('MODE ' +
-                                                   irc_channel + ' -o ' +
-                                                   w[2]);
-                                       continue;
-                               } else if (on_channel &&
-                                   msg.match(/^!VOICE [^\b]* [^\b]*$/)
-                                   != null) {
-                                       w = msg.split(' ');
-                                       if (w[1] == irc_voice_passwd)
-                                               this.putline('MODE ' +
-                                                   irc_channel + ' +v ' +
-                                                   w[2]);
-                                       continue;
-                               } if (on_channel &&
-                                   msg.match(/^!DEVOICE [^\b]* [^\b]*$/)
-                                   != null) {
-                                       w = msg.split(' ');
-                                       if (w[1] == irc_voice_passwd)
-                                               this.putline('MODE ' +
-                                                   irc_channel + ' -v ' +
-                                                   w[2]);
-                                       continue;
-                               } else if (on_channel &&
-                                   msg.match(/^!BAN [^\b]* [^\b]* [^\b]*$/)
-                                   != null) {
-                                       w = msg.split(' ');
-                                       if (w[1] == irc_ban_passwd) {
-                                               this.putline('MODE ' +
-                                                   irc_channel + ' +b ' +
-                                                   w[3]);
-                                               this.putline('KICK ' +
-                                                   irc_channel + ' ' +
-                                                   w[2] + ' :relayed ban');
-                                       }
-                                       continue;
-                               } else if (on_channel &&
-                                   msg.match(/^!DEBAN [^\b]* [^\b]*$/)
-                                   != null) {
-                                       w = msg.split(' ');
-                                       if (w[1] == irc_ban_passwd) {
-                                               this.putline('MODE ' +
-                                                   irc_channel + ' -b ' +
-                                                   w[2]);
-                                       }
-                                       continue;
-                               } else if (msg.match(/^!QUIT [^\b]*$/)
-                                   != null) {
-                                       w = msg.split(' ');
-                                       if (w[1] == irc_quit_passwd) {
-                                               should_quit = true;
-                                               break;
-                                       }
-                                       continue;
-                               } else if ((s = msg.match(
-                                   /^!PM [^\b]* [^\b]* :/)) != null) {
-                                       s = s.toString();
-                                       w = msg.split(' ');
-                                       if (w[1] == irc_msg_passwd)
-                                               this.putline('PRIVMSG ' +
-                                                   w[2] + ' :' +
-                                                   msg.substr(s.length));
-                                       continue;
-                               } else if (on_channel &&
-                                   (s = msg.match(/^!M [^\b]* :/)) != null) {
-                                       s = s.toString();
-                                       w = msg.split(' ');
-                                       if (w[1] == irc_msg_passwd)
-                                               this.putline('PRIVMSG ' +
-                                                   irc_channel + ' :' +
-                                                   msg.substr(s.length));
-                                       continue;
-                               } else if (on_channel &&
-                                   (s = msg.match(/^!A [^\n]* :/)) != null) {
-                                       s = s.toString();
-                                       w = msg.split(' ');
-                                       if (w[1] == irc_msg_passwd)
-                                               this.putline('PRIVMSG ' +
-                                                   irc_channel +
-                                                   " :\001ACTION " +
-                                                   msg.substr(s.length) +
-                                                   "\001");
-                                       continue;
-                               }
-                       }
-               }
-       }
-
-       return false;
-}
-
-function main()
-{
-       var server;
-       var fd;
-       var fh;
-       var line;
-
-       log_init();
-       should_quit = false;
-
-       for (;;) { try {
-               on_channel = false;
-               join_attempts = 0;
-
-               server = select_server();
-               stdout.write(log_timestamp() + ' -+- Connecting to ' +
-                   server.address + ':' + server.port + "\n");
-               fd = new FD();
-               fd.socket(FD.AF_INET, FD.SOCK_STREAM, 0);
-               fd.connect(server.address, server.port);
-               fd.setsockopt(FD.SO_KEEPALIVE, 1);
-               fh = new File(fd.fd, 'r+');
-               fh.setvbuf(File._IOLBF, 0);
-               fh.putline('USER ' + irc_user + ' hostname servername :' +
-                   irc_name);
-               fh.state = File.prototype.state_nick;
-               for (;;) {
-                       if (!fh.state())
-                               break;
-               }
-               if (on_channel)
-                       fh.putline('PART ' + irc_channel + ' :' +
-                                  irc_part_message);
-               fh.putline('QUIT :' + irc_quit_message);
-       } catch (x) {
-               stdout.write(log_timestamp() + ' -+- Error: ' + x + "\n");
-       }
-       try {
-               fh.close();
-               fd.close();
-       } catch (x) {}
-       stdout.write(log_timestamp() + ' -+- Disconnected from ' +
-           server.address + ':' + server.port + "\n");
-       if (should_quit)
-               break;
-       sleep(irc_reconnect_delay);
-       }
-}
-
-main();
diff --git a/mmsoftware/js/js-sh/app/randstat/randstat.js b/mmsoftware/js/js-sh/app/randstat/randstat.js
deleted file mode 100644 (file)
index ba72017..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Configuration;  Modify as necessary
- */
-var possibilities = 4;
-var maxloops = 10000;
-
-/*
- * Variables
- */
-var results = [], found = [];
-var total, loop, i, rnd, found_total;
-
-/*
- * Returns a random number between 0 and possibilities - 1
- */
-function random_possibility()
-{
-
-       return Math.floor(Math.random() * possibilities);
-}
-
-/*
- * To get reasonable statistics, sample maxloops times
- */
-for (loop = 0; loop < maxloops; loop++) {
-
-       /*
-        * Flag all possibilities as unprocessed, as well as our processed
-        * possibilities counter which we'll use as optimization
-        */
-       for (i = 0; i < possibilities; i++)
-               found[i] = false;
-       found_total = 0;
-
-       /*
-        * Loop indefinitely increasing total from zero
-        */
-       for (total = 0; ; total++) {
-               rnd = random_possibility();
-               if (!found[rnd]) {
-                       /*
-                        * New unprocessed possibility occured, flag as such
-                        * and increase our processed possibilities by one.
-                        * Then verify if our counter reached the number of
-                        * possibilities, in which case they all were
-                        * satisfied.  We then record/mark a point in our
-                        * sparse results array and break this innner loop.
-                        */
-                       found[rnd] = true;
-                       if (++found_total == possibilities) {
-                               if (results[total] == undefined)
-                                       results[total] = 0;
-                               results[total]++;
-                               break;
-                       }
-               }
-       }
-
-}
-
-/*
- * For every existing result, print its score
- */
-stdout.write("Iterat.\t= Frequency:\n");
-for (total = results.length, i = 0; i < total; i++) {
-       if (results[i] != undefined)
-               stdout.write((i + 1) + "\t= " + results[i] + "\n");
-}
-
-/*
- * XXX TODO XXX
- * - It would be nice to automatically create a graphic with the results
- */
diff --git a/mmsoftware/js/js-sh/app/thumb/thumb.js b/mmsoftware/js/js-sh/app/thumb/thumb.js
deleted file mode 100644 (file)
index a4f561a..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/* $Id: thumb.js,v 1.8 2006/11/06 04:03:58 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * TODO:
- * - Implement getopt-like class and allow to provide command line arguments
- * - Generate multiple indexes with list of index links at top and bottom
- *   for large directories
- * - Work on better presentation
- */
-
-function thumbnail_jpeg(fh)
-{
-       this.jpeg(fh, 50);
-}
-
-function thumbnail(from, to, xmax, ymax)
-{
-       var ofh, tfd, nfd, oimg, ox, oy, timg, tfh;
-       var ret = false;
-       var type = undefined;
-       var i, to;
-
-       /* XXX */
-       stderr.write('Processing: ' + from + "\n");
-
-       /*
-        * Set load and save functions relative to image file type.
-        */
-       if (from.match(/\.jpg$|\.jpeg$/)) {
-               GD.load = GD.createFromJpeg;
-               GDImage.prototype.save = thumbnail_jpeg;
-       } else if (from.match(/\.png$/)) {
-               GD.load = GD.createFromPng;
-               GDImage.prototype.save = GDImage.prototype.png;
-       } else if (from.match(/\.gif$/)) {
-               GD.load = GD.createFromGif;
-               GDImage.prototype.save = GDImage.prototype.gif;
-       }
-
-       /*
-        * We use a single try block which breaks out of for before setting
-        * res to true.  We use a dummy for loop since goto doesn't work.
-        */
-       for (;;) {
-               try {
-                       var otime, tstat;
-
-                       /*
-                        * First open descriptors so that we may fstat(2)
-                        * to determine if the thumbnail is more recent than
-                        * the original image, in which case we don't avoid to
-                        * create a thumb for nothing.  We'll use File's
-                        * fdopen(3) functionality afterwards if need be.
-                        * We do this because image resizing is a rather CPU
-                        * intensive operation.
-                        */
-                       ofd = new FD();
-                       ofd.open(from, FD.O_RDONLY);
-                       otime = (ofd.fstat()).st_mtime;
-
-                       tfd = new FD();
-                       tfd.open(to, FD.O_WRONLY | FD.O_CREAT);
-                       tstat = tfd.fstat();
-
-                       if (otime <= tstat.st_mtime && tstat.st_size != 0) {
-                               ofd.close();
-                               tfd.close();
-                               return true;
-                       }
-
-                       /*
-                        * Load original image and determine thumb size.
-                        */
-                       ofh = new File(ofd.fd, 'r');
-                       oimg = GD.load(ofh);
-
-                       ox = oimg.imageSX();
-                       oy = oimg.imageSY();
-                       if (ox <= xmax && oy <= ymax) {
-                               tx = ox;
-                               ty = oy;
-                       } else if (ox < oy) {
-                               tx = Math.round((xmax / oy) * ox);
-                               ty = ymax;
-                       } else {
-                               tx = xmax;
-                               ty = Math.round((ymax / ox) * oy);
-                       }
-
-                       /*
-                        * Create and save new thumbnail.  It's important to
-                        * first truncate the file to zero length which
-                        * fopen(3) would have done for us but which fdopen(3)
-                        * won't.
-                        */
-                       tfd.ftruncate(0);
-                       tfh = new File(tfd.fd, 'w');
-
-                       timg = GD.createTrueColor(tx, ty);
-                       //oimg.copyResampled(timg, 0, 0, 0, 0, tx, ty, ox, oy);
-                       oimg.copyResized(timg, 0, 0, 0, 0, tx, ty, ox, oy);
-
-                       timg.save(tfh);
-               } catch (x) {
-                       Syslog.log(Syslog.LOG_NOTICE, x + ' (' + from + ')');
-                       break;
-               }
-
-               /* Success */
-               ret = true;
-               break;
-       }
-
-       /*
-        * We close/destroy the objects in the same order they appeared since
-        * if we get an exception the others won't execute.  Although the
-        * language supports a GC and objects will eventually be destroyed,
-        * there's no point in leaving them dangling unnecessary resources for
-        * a while.  File descriptors shouldn't be open for nothing, and
-        * images take up a lot of memory.
-        */
-       try {
-               ofh.close();
-               oimg.destroy();
-               tfh.close();
-               timg.destroy();
-       } catch (x) {}
-
-       delete GD.load;
-       delete GDImage.prototype.save;
-
-       return ret;
-}
-
-function thumbnail_dir(path, xmax, ymax)
-{
-       var dir, fh;
-       var ret = false;
-       var i, f, index = [];
-
-       for (;;) {
-               try {
-
-               dir = new Dir(path);
-               while ((e = dir.read()) != null) {
-                       if ((e.type & Dir.DT_DIR) != 0 &&
-                           e.name.charAt(0) != '.') {
-                               index.push({t: 'DIR', l: e.name});
-                               if (!thumbnail_dir(path + '/' + e.name, xmax,
-                                   ymax))
-                                       break;
-                       } else if ((e.type & Dir.DT_REG) != 0 && e.name.match(
-                           /\.jpg$|\.jpeg$|\.png$|\.gif$/)) {
-                               if (e.name.match(/_thumb/))
-                                       continue;
-                               i = e.name.lastIndexOf('.');
-                               newname = e.name.substring(0, i) + '_thumb' +
-                                   e.name.substring(i);
-                               if (!thumbnail(path + '/' + e.name, path +
-                                   '/' + newname, xmax, ymax))
-                                       break;
-                               index.push({t: 'IMG', o: e.name, n: newname});
-                       }
-               }
-               if (index.length == 0) {
-                       ret = true;
-                       break;
-               }
-               /* XXX sort */
-               fh = new File(path + '/index.html', 'w');
-               fh.write("<html><head></head><body>\n" +
-                   '<br><a href="../index.html">../ (parent directory)' +
-                   "</a><br><br>\n");
-               for (i in index) {
-                       f = index[i];
-                       if (f.t == 'DIR') {
-                               var t;
-
-                               fh.write('<table border="1"><tr><td width="' +
-                                   xmax + '" height="' + ymax +
-                                   '" valign="center" align="center">' +
-                                   '<a href="' + f.l + '/index.html">');
-                               if ((t = dir_findthumb(path + '/' + f.l))
-                                   != null)
-                                       fh.write('<img src="' + f.l + '/' + t +
-                                           '">');
-                               fh.write('</a></td></tr><tr><td align="' +
-                                   'center" valign="center"><a href="' + f.l +
-                                   '/index.html">' + f.l + '/</a></td>' +
-                                   "</tr></table>\n");
-                       }
-               }
-               for (i in index) {
-                       f = index[i];
-                       if (f.t == 'IMG')
-                               fh.write('<a target="_blank" href="' + f.o +
-                                   '"><img src="' + f.n + '"></a>' + "\n");
-               }
-               fh.write('<br><sub>Thumb gallery generated by: ' +
-                   '$Id: thumb.js,v 1.8 2006/11/06 04:03:58 mmondor Exp $' +
-                   '<br><a href="http://cvs.pulsar-zone.net/cgi-bin/' +
-                   'cvsweb.cgi/mmondor/mmsoftware/js/js-sh/app/thumb/' +
-                   'thumb.js">(source)</a></sub>' + "\n");
-               fh.write("</body></html>\n");
-               fh.close();
-
-               } catch (x) {
-                       Syslog.log(Syslog.LOG_NOTICE, x.toString());
-                       break;
-               }
-
-               ret = true;
-               break;
-       }
-
-       try {
-               dir.close();
-               fh.close();
-       } catch (x) {}
-
-       return ret;
-}
-
-function dir_findthumb(path)
-{
-       var ret = null;
-       var dir, e, o, s = 0;
-
-       for (;;) {
-               try {
-                       dir = new Dir(path);
-                       while ((e = dir.read()) != null) {
-                               if (e.name.match(/_thumb/)) {
-                                       o = FS.stat(path + '/' + e.name);
-                                       if (o.st_size > s)
-                                               ret = e.name;
-                               }
-                       }
-               } catch (x) {
-                       Syslog.log(Syslog.LOG_NOTICE, x.toString());
-                       break;
-               }
-               break;
-       }
-
-       try {
-               dir.close();
-       } catch (x) {}
-
-       return ret;
-}
-
-thumbnail_dir('/home/data/jshttpd/mmondor/img_gallery', 100, 100);
diff --git a/mmsoftware/js/js-sh/src/GNUmakefile b/mmsoftware/js/js-sh/src/GNUmakefile
deleted file mode 100644 (file)
index bfa0bc1..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# $Id: GNUmakefile,v 1.7 2006/10/28 22:02:52 mmondor Exp $
-
-#CFLAGS += -g
-CFLAGS += -Wall
-
-JS_CFLAGS := $(shell spidermonkey-config -dc)
-JS_LDFLAGS := $(shell spidermonkey-config -dl)
-
-PG_CFLAGS := $(shell pg_config --cppflags)
-PG_LDFLAGS := $(shell pg_config --ldflags)
-PG_LDFLAGS += -lpq
-
-GD_CFLAGS := $(shell gdlib-config --cflags)
-GD_LDFLAGS := $(shell gdlib-config --ldflags --libs)
-GD_LDFLAGS += -lgd
-
-MMOBJS := $(addprefix ../../../mmlib/,mmpool.o mmhash.o mmlog.o mmstring.o)
-JSOBJS := $(addprefix ../../classes/,js_gcroot.o js_fd.o js_errno.o \
-       js_signal.o js_file.o js_pgsql.o js_dir.o js_fs.o js_gd.o js_syslog.o)
-
-CFLAGS += $(JS_CFLAGS) $(PG_CFLAGS) $(GD_CFLAGS) -I../../../mmlib \
-       -I../../classes
-LDFLAGS += $(JS_LDFLAGS) $(PG_LDFLAGS) $(GD_LDFLAGS)
-
-OBJ := js-sh.o
-
-
-all: js-sh
-
-%.o: %.c
-       cc -c $(CFLAGS) -o $@ $<
-
-js-sh: $(OBJ) $(MMOBJS) $(JSOBJS)
-       cc -o $@ $(OBJ) $(LDFLAGS) -lc $(MMOBJS) $(JSOBJS)
-
-clean:
-       rm -f js-sh $(OBJ) $(MMOBJS) $(JSOBJS)
diff --git a/mmsoftware/js/js-sh/src/js-sh.c b/mmsoftware/js/js-sh/src/js-sh.c
deleted file mode 100644 (file)
index 3937020..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/* $Id: js-sh.c,v 1.10 2006/10/28 22:02:52 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2005, Matthew Mondor
- */
-
-/*
- * TODO:
- *
- * - Verify with Brendan Eich:
- *   - If reusing the context to execute several other scripts, it is
- *     important that they not be able to add global properties or methods.
- *     This seems to currently work using a custom api_class_property_add().
- *     This however also required standard properties to be shared
- *     (JS_PROP_SHARED), otherwise api_class_property_add() would be called
- *     and even setting values to existing API system properties would fail in
- *     user scripts.  Scealing was also too strict.
- *     I assumed that JS_AddNamedRoot() was required for the API class to
- *     never be freed, so that it can be reused after a call to
- *     js_context_reset().  Perhaps this is not necessary.
- */
-
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include <assert.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <jsapi.h>
-
-#include <js_gcroot.h>
-#include <js_fd.h>
-#include <js_errno.h>
-#include <js_signal.h>
-#include <js_file.h>
-#include <js_pgsql.h>
-#include <js_dir.h>
-#include <js_gd.h>
-#include <js_syslog.h>
-
-
-
-/*
- * DEFINITIONS
- */
-
-/* Size runtime objects must take to run the GC */
-#define GCBYTES    1048576 /* 1MB */
-
-/* Size of stack to allocate for every context */
-#define STACKBYTES 8192    /* 8KB */
-
-/*
- * Structure used to link a context with custom objects we need to perform
- * some cleanup from before destroying the context.  Ideally managed via
- * mmpool(3) in a real world application for slap management and recycling.
- * We'll have one of these per process in our pool of processes.
- */
-typedef struct {
-       JSRuntime       *rt;
-       JSContext       *ctx;
-       JSObject        *global, *class_syslog, *class_fd, *class_errno,
-                       *class_signal, *class_file, *class_pgsql, *class_dir,
-                       *class_gd;
-} js_context_t;
-
-/*
- * To hold loaded file objects (actually mmap(2)ed)
- */
-typedef struct {
-       void            *data;
-       size_t          size;
-} file_t;
-
-/*
- * Defaults for the global class
- */
-static JSClass global_class = {
-       "global", 0, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
-};
-
-
-
-/*
- * PROTOTYPES
- */
-
-int                    main(int, char **);
-static JSBool          branch_callback(JSContext *, JSScript *);
-static void            context_error_reporter(JSContext *, const char *,
-                           JSErrorReport *);
-
-static file_t          *file_load(const char *);
-static void            file_free(file_t *);
-
-/* Could be an exported API later on */
-static js_context_t    *js_context_init(size_t, size_t);
-static void            js_context_destroy(js_context_t *);
-/* XXX static void             js_context_reset(js_context_t *);*/
-
-
-
-
-
-int
-main(int argc, char **argv)
-{
-       file_t          *file;
-       js_context_t    *cctx;
-
-       if (argc != 2) {
-               (void) fprintf(stderr, "Usage: js-sh <scriptfile>\n");
-               exit(EXIT_FAILURE);
-       }
-       if ((file = file_load(argv[1])) == NULL) {
-               (void) fprintf(stderr, "Error loading '%s'\n", argv[1]);
-               exit(EXIT_FAILURE);
-       }
-
-       /* Ignore SIGPIPE signal */
-       {
-               struct sigaction        act;
-
-               act.sa_handler = SIG_IGN;
-               act.sa_flags = SA_NOCLDSTOP;
-               (void) sigemptyset(&act.sa_mask);
-               (void) sigaction(SIGPIPE, &act, NULL);
-       }
-
-       /*
-        * We always need at least one runtime per process, at least one
-        * context per thread and at least a global object per context
-        * (standard classes, like Date).
-        */
-       if ((cctx = js_context_init(GCBYTES, STACKBYTES)) == NULL) {
-               file_free(file);
-               (void) fprintf(stderr, "js_context_init()\n");
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * This is a very useful and important feature, enable our callback
-        * function which will get called whenever the script branches
-        * backwards, returns from a function or exits. It allows us to
-        * even maintain control in cases where the script loops endlessly.
-        */
-       (void) JS_SetBranchCallback(cctx->ctx, branch_callback);
-       /* And error reporter */
-       (void) JS_SetErrorReporter(cctx->ctx, context_error_reporter);
-
-       /*
-        * Now execute script loaded into our file_t.
-        * We simplify this process by calling JS_EvaluateScript() which
-        * will first tokenize/compile the result, and then interpret/run it.
-        * Moreover, it allows the script to optionally return a value
-        * directly like if it was a function.
-        * Alternatively, we could use JS_CompileFile() or JS_CompileScript()
-        * to pre-tokenize the script, and JS_ExecuteScript() to interpret it.
-        */
-       {
-               jsval           rval;
-               JSString        *str;
-
-               if (JS_EvaluateScript(cctx->ctx, cctx->global, file->data,
-                   file->size, argv[1], 1, &rval)) {
-                       str = JS_ValueToString(cctx->ctx, rval);
-                       (void) fprintf(stderr, "Script result: %s\n",
-                           JS_GetStringBytes(str));
-               } else {
-                       /* XXX how to obtain error and stack backtrace? */
-               }
-       }
-
-       /* Cleanup */
-       file_free(file);
-       js_context_destroy(cctx);
-
-       exit(EXIT_SUCCESS);
-}
-
-/*
- * This function is called during the execution of the script so that we can
- * remain in control of the application. If we only allow the scripts to
- * define functions for callbacks, we can use the first instance if this event
- * to abort the script if wanted, as well. We can then set an alternative
- * callback function and execute the script provided functions at specific
- * events. Of course, it also would be possible to use setitimer(2) to have
- * a SIGALRM signal trigger a function at regular set intervals.
- */
-/* ARGSUSED */
-static JSBool
-branch_callback(JSContext *ctx, JSScript *script)
-{
-       static int      count = 0;
-
-       if (++count > 0x3fff) {
-               count = 0;
-               JS_MaybeGC(ctx);
-       }
-
-       /* Returning JS_FALSE here aborts the script */
-       return JS_TRUE;
-}
-
-static void
-context_error_reporter(JSContext *cx, const char *msg, JSErrorReport *rep)
-{
-       (void) fprintf(stderr, "context_error_reporter() - %s : %s",
-           msg, rep->linebuf);
-}
-
-
-
-/*
- * Could be an exported API
- */
-
-static js_context_t *
-js_context_init(size_t gc_size, size_t stack_size)
-{
-       js_context_t    *cctx;
-
-       if ((cctx = malloc(sizeof(js_context_t))) == NULL ||
-           (cctx->rt = JS_NewRuntime(gc_size)) == NULL ||
-           !js_map_init() ||
-           (cctx->ctx = JS_NewContext(cctx->rt, stack_size)) == NULL ||
-           (cctx->global = JS_NewObject(cctx->ctx, &global_class, NULL,
-               NULL)) == NULL ||
-           !JS_InitStandardClasses(cctx->ctx, cctx->global) ||
-           !js_InitGCRoot(cctx->ctx) ||
-           (cctx->class_syslog = js_InitSyslogClass(cctx->ctx, cctx->global))
-               == NULL ||
-           (cctx->class_fd = js_InitFDClass(cctx->ctx, cctx->global))
-               == NULL ||
-           (cctx->class_errno = js_InitErrnoClass(cctx->ctx, cctx->global))
-               == NULL ||
-           (cctx->class_signal = js_InitSignalClass(cctx->ctx, cctx->global))
-               == NULL ||
-           (cctx->class_file = js_InitFileClass(cctx->ctx, cctx->global))
-               == NULL ||
-           (cctx->class_pgsql = js_InitPGClass(cctx->ctx, cctx->global))
-               == NULL  ||
-           (cctx->class_dir = js_InitDirClass(cctx->ctx, cctx->global))
-               == NULL ||
-           (cctx->class_gd = js_InitGDClass(cctx->ctx, cctx->global))
-               == NULL) {
-               /* An error, free any partially allocated resources */
-               if (cctx != NULL)
-                       js_context_destroy(cctx);
-
-               return NULL;
-       }
-
-       return cctx;
-}
-
-static void
-js_context_destroy(js_context_t *cctx)
-{
-
-       assert(cctx != NULL);
-
-       if (cctx->ctx != NULL) {
-               js_DestroyGCRoot(cctx->ctx);
-               JS_DestroyContext(cctx->ctx);
-       }
-       js_map_destroy();
-       if (cctx->rt != NULL)
-               JS_DestroyRuntime(cctx->rt);
-
-       free(cctx);
-}
-
-/*
- * This function should permit to restore the context to a consistent, known
- * state before a new script can be executed using the same context instead of
- * having to destroy and recreate contexts everytime.
- */
-/* ARGSUSED */
-/* XXX
-static void
-js_context_reset(js_context_t *cctx)
-{
-
-}
-*/
-
-
-/*
- * Loads specified file and returns a file_t pointer.  Note that we only
- * internally keep the memory map for read access to the file, rather than an
- * open filedescriptor.
- */
-static file_t *
-file_load(const char *filename)
-{
-       int             fd;
-       struct stat     st;
-       file_t          *file;
-
-       assert(filename != NULL);
-
-       if ((fd = open(filename, O_RDONLY)) != -1) {
-               if (fstat(fd, &st) == 0) {
-                       if ((file = malloc(sizeof(file_t))) != NULL) {
-                               file->size = (size_t)st.st_size;
-
-                               if ((file->data = mmap(NULL, file->size,
-                                   PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0))
-                                   != MAP_FAILED) {
-                                       (void) close(fd);
-                                       return file;
-                               }
-
-                               free(file);
-                       }
-               }
-               (void) close(fd);
-       }
-
-       return NULL;
-}
-
-/*
- * Frees a file_t which was returned by a previous file_load() call.
- */
-static void
-file_free(file_t *file)
-{
-
-       assert(file != NULL);
-
-       (void) munmap(file->data, file->size);
-       free(file);
-}
diff --git a/mmsoftware/js/jslib/fd.js b/mmsoftware/js/jslib/fd.js
deleted file mode 100644 (file)
index 953261a..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-/* $Id: fd.js,v 1.11 2006/08/22 14:08:45 mmondor Exp $ */
-
-/*
- * Copyright (C) 2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Extend FD object with buffered read/write functions to be used on
- * non-blocking descriptors.
- *
- * XXX TODO XXX
- * - Fix so that it is possible to read/write without polling,
- *   for use by httpd.js for instance.
- */
-
-
-
-FD.prototype.bread_buffer = '';
-FD.prototype.bwrite_buffer = '';
-FD.prototype.input_timeout = 30000;
-FD.prototype.output_timeout = 30000;
-
-FD.prototype.berror = 0;
-FD.prototype.BSUCCESS  = 0;
-FD.prototype.BEAGAIN   = 1;
-FD.prototype.BEOF      = 2;
-FD.prototype.BTIMEOUT  = 3;
-FD.prototype.BTOOLONG  = 4;
-FD.prototype.BERROR    = 5;    /* To delegate to errno */
-
-FD.prototype.berrorStr = {
-       0: "Success",
-       1: "No data available",
-       2: "End of file",
-       3: "Timeout",
-       4: "Line too long",
-       5: "Other error"
-};
-
-/*
- * Initializes state for a buffered FD out of a specified file descriptor int
- */
-FD.prototype.binit = function(fd, input_timeout, output_timeout)
-{
-       this.set(fd);
-       this.fcntl(FD.F_SETFL, FD.O_NONBLOCK);
-       this.input_timeout = input_timeout;
-       this.output_timeout = output_timeout;
-}
-
-/*
- * Resets timeouts for a buffered FD
- */
-FD.prototype.btimeouts = function(input_timeout, output_timeout)
-{
-       this.input_timeout = input_timeout;
-       this.output_timeout = output_timeout;
-}
-
-/*
- * Reads at most <max> bytes, using buffering internally as necessary when
- * reading.  If the data is already available it is immediately returned.
- * Returns null on error or EOF, or a String holding the read data.
- * If no data is available, polling is performed for at most input_timeout
- * milliseconds.
- */
-FD.prototype.bread = function(max, poll)
-{
-       var data = '';
-       var e;
-
-       if (max == 0)
-               return '';
-
-       while (this.bread_buffer.length == 0) {
-               try {
-                       data = this.read(max);
-                       if (data.length == 0) {
-                               this.berror = this.BEOF;
-                               return null;
-                       }
-               } catch (x) {
-                       if (this.errno != Errno.EAGAIN)
-                               return null;
-                       data = '';
-                       this.berror = this.BERROR;
-               }
-               if (data.length != 0)
-                       this.bread_buffer += data;
-               else {
-                       if (!poll) {
-                               this.berror = this.BEAGAIN;
-                               return data;
-                       }
-                       try {
-                               this.events = FD.POLLIN;
-                               e = FD.poll([this], this.input_timeout);
-                               if (e.length == 0) {
-                                       this.berror = this.BTIMEOUT;
-                                       return null;
-                               }
-                               if ((e[0].revents & (FD.POLLHUP | FD.POLLERR))
-                                   != 0) {
-                                       this.berror = this.BEOF;
-                                       return null;
-                               }
-                       } catch (x) {
-                               this.berror = this.BERROR;
-                               return null;
-                       }
-               }
-       }
-
-       data = this.bread_buffer.substr(0, max);
-       this.bread_buffer = this.bread_buffer.substr(data.length);
-
-       this.berror = 0;
-       return data;
-}
-
-/*
- * Re-inserts the specified data into the read buffer so that next read should
- * retreive it first.
- */
-FD.prototype.bunread = function(data)
-{
-       this.bread_buffer = data + this.bread_buffer;
-}
-
-/*
- * Writes specified data to a buffer, and flush the buffer as necessary if the
- * buffer is too large.  Returns 0 on success, or -1 on error.  May also
- * return 1 if poll is false and there is data to flush exceeding the 64KB
- * buffer.
- */
-FD.prototype.bwrite = function(data, immediate, poll)
-{
-       if (data.length == 0)
-               return 0;
-
-       if (immediate) {
-               var len;
-
-               try {
-                       len = this.write(data);
-                       if (len < 1) {
-                               this.events &= ~FD.POLLOUT;
-                               this.berror = this.BERROR;
-                               return -1;
-                       }
-               } catch (x) {
-                       if (this.errno != Errno.EAGAIN) {
-                               this.events &= ~FD.POLLOUT;
-                               this.berror = this.BERROR;
-                               return -1;
-                       }
-               }
-               if (len == data.length) {
-                       this.events &= ~FD.POLLOUT;
-                       return 0;
-               }
-
-               this.bwrite_buffer += data.substr(len);
-               /* FALLTHROUGH */
-       } else
-               this.bwrite_buffer += data;
-
-       this.events |= FD.POLLOUT;
-       if (this.bwrite_buffer.length > 65534)
-               return this.bflushw(poll);
-
-       return 1;
-}
-
-/*
- * Clears the read buffer, if any bytes were ready.
- */
-FD.prototype.bflushr = function()
-{
-       this.bread_buffer = '';
-}
-
-/*
- * Attempts to flush the write buffer, returning -1 on error, 0 on success.
- * Polls as necessary for as up to output_timeout milliseconds.
- * If poll is false, but that there remains data to be flushed, returns 1,
- * with berror set to BEAGAIN.
- */
-FD.prototype.bflushw = function(poll)
-{
-       var len;
-       var e;
-
-       while (this.bwrite_buffer.length > 0) {
-               try {
-                       len = this.write(this.bwrite_buffer);
-                       if (len < 1) {
-                               this.events &= ~FD.POLLOUT;
-                               this.berror = this.BERROR;
-                               return -1;
-                       }
-               } catch (x) {
-                       if (this.errno != Errno.EAGAIN) {
-                               this.events &= ~FD.POLLOUT;
-                               this.berror = this.BERROR;
-                               return -1;
-                       }
-               }
-               this.bwrite_buffer = this.bwrite_buffer.substr(len);
-               if (this.bwrite_buffer.length == 0)
-                       break;
-               if (!poll) {
-                       this.berror = this.BEAGAIN;
-                       this.events |= FD.POLLOUT;
-                       return 1;
-               }
-               try {
-                       this.events = FD.POLLOUT;
-                       e = FD.poll([this], this.output_timeout);
-                       if (e.length == 0) {
-                               this.berror = this.BTIMEOUT;
-                               return -1;
-                       }
-                       if ((e[0].revents & (FD.POLLHUP | FD.POLLERR)) != 0) {
-                               this.berror = this.BEOF;
-                               return -1;
-                       }
-               } catch (x) {
-                       this.berror = this.BEOF;
-                       return -1;
-               }
-       }
-
-       this.berror = this.BSUCCESS;
-       this.events &= ~FD.POLLOUT;
-       return 0;
-}
-
-/*
- * Internally uses buffered reads, waiting until a maximum number of bytes
- * have been read or EOF occurs (in which case it returns null), or until a
- * full '\r\n' delimited line could be read, in which case the line is returned
- * and extraneous data buffered for further reads.  The returned line will not
- * have the trailing "\r\n".  If poll is false, it may also return null but
- * with a berror of BEAGAIN.
- */
-FD.prototype.breadline = function(max, poll)
-{
-       var data = '';
-       var data2;
-       var idx;
-
-       while (data.length < max) {
-               if ((data2 = this.bread(max - data.length, poll)) == null)
-                       return null;
-               data += data2;
-               if ((idx = data.indexOf("\r\n")) != -1) {
-                       this.bunread(data.substr(idx + 2));
-                       return data.substr(0, idx);
-               }
-               /*
-                * XXX For some reason this doesn't work with stdin, only
-                * SOCK_STREAM sockets descriptors.  Needed in case we are not
-                * polling because although bread() would return null with
-                * BEAGAIN in case it doesn't poll and no data remains in the
-                * buffer to provide, if there is buffered data but no new
-                * data to read, we could loop endlessly taking a lot of CPU
-                * time until an EOL is really detected.
-                */
-               if (!poll) {
-                       this.bunread(data2);
-                       this.berror = this.BEAGAIN;
-                       return null;
-               }
-       }
-
-       this.bunread(data);
-       this.berror = this.BTOOLONG;
-       return null;
-}
diff --git a/mmsoftware/js/jslib/json.js b/mmsoftware/js/jslib/json.js
deleted file mode 100644 (file)
index 7d6e428..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/* $Id: json.js,v 1.3 2006/11/18 03:03:58 mmondor Exp $ */
-
-/*
- * Copyright (C) 2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Safe JSON object parser.
- * This implementation expects a base object to be supplied, into which there
- * can be other objects and arrays, as well as native elements.
- * Designed to parse strings possibly containing user-provided data.
- * Note that this implementation is not thread-reentrant safe, although it
- * would be easy to adapt to make it so, wrapping the state information into
- * an object which would need to be instantiated once per thread.
- */
-
-var json_rlevel = 0, json_rlevel_max = 0;
-var json_str = '';
-var json_len = 0;
-var json_error = 'Success';
-
-function json_parse(s, rmax)
-{
-       var o;
-
-       if (s.substr(0, 1) == '(' && s.substr(s.length - 1, 1) == ')')
-               s = s.substr(1, s.length - 2);
-
-       json_rlevel = 0;
-       json_rlevel_max = rmax;
-       json_str = s;
-       json_len = s.length;
-       json_off = 0;
-       json_error = 'Success';
-
-       o = {};
-       if (!json_parse_object(o))
-               return undefined;
-       return o;
-}
-
-function json_isnumdigit(c)
-{
-       return ((c >= '0' && c <= '9') || c == '-' || c == '+' || c == '.' ||
-           c == 'e' || c == 'E');
-}
-
-function json_parse_r()
-{
-       var o, s;
-
-       if (++json_rlevel > json_rlevel_max) {
-               --json_rlevel;
-               json_error = 'Recursion level exceeded';
-               return undefined;
-       }
-
-       for (; json_off < json_len; ) {
-               if (json_str.charAt(json_off) == ' ') {
-                       json_off++;
-                       continue;
-               }
-               /* Object */
-               if (json_str.charAt(json_off) == '{') {
-                       o = {};
-                       if (!json_parse_object(o))
-                               return undefined;
-                       --json_rlevel;
-                       return o;
-               }
-               /* Array */
-               if (json_str.charAt(json_off) == '[') {
-                       o = [];
-                       if (!json_parse_array(o))
-                               return undefined;
-                       --json_rlevel;
-                       return o;
-               }
-               /* String */
-               if (json_str.charAt(json_off) == '"') {
-                       for (json_off++, s = ''; json_off < json_len &&
-                           json_str.charAt(json_off) != '"'; json_off++)
-                               s += json_str.charAt(json_off);
-                       if (json_str.charAt(json_off) != '"') {
-                               --json_rlevel;
-                               json_error = 'Missing end of string quote';
-                               return undefined;
-                       }
-                       json_off++;
-                       --json_rlevel;
-                       return s;
-               }
-               /* Various constants */
-               if (json_str.substr(json_off, 9) == 'undefined') {
-                       json_off += 9;
-                       --json_rlevel;
-                       return undefined;
-               }
-               if (json_str.substr(json_off, 4) == 'null') {
-                       json_off += 4;
-                       --json_rlevel;
-                       return null;
-               }
-               if (json_str.substr(json_off, 4) == 'true') {
-                       json_off += 4;
-                       --json_rlevel;
-                       return true;
-               }
-               if (json_str.substr(json_off, 5) == 'false') {
-                       json_off += 5;
-                       --json_rlevel;
-                       return false;
-               }
-               if (json_str.substr(json_off, 3) == 'NaN') {
-                       json_off += 3;
-                       --json_rlevel;
-                       return NaN;
-               }
-               if (json_str.substr(json_off, 8) == 'Infinity') {
-                       json_off += 8;
-                       --json_rlevel;
-                       return Infinity;
-               }
-               /* Number */
-               for (s = ''; json_off < json_len &&
-                   json_isnumdigit(json_str.charAt(json_off)); json_off++)
-                       s += json_str.charAt(json_off);
-               --json_rlevel;
-               if (s.length > 0)
-                       return new Number(s);
-               else {
-                       json_error = 'Invalid data element';
-                       return undefined;
-               }
-       }
-
-       --json_rlevel;
-       json_error = 'End of string reached';
-       return undefined;
-}
-
-function json_parse_object(o)
-{
-       var key;
-
-       /* Skip spaces */
-       for (; json_off < json_len &&
-           json_str.charAt(json_off) == ' ';
-           json_off++) ;
-       /* Make sure we start with '{' */
-       if (json_str.charAt(json_off) != '{') {
-               json_error = '{ expected to start an object';
-               return false;
-       }
-       json_off++;
-
-       for (; json_off < json_len; ) {
-               /* Skip spaces */
-               for (; json_off < json_len &&
-                   json_str.charAt(json_off) == ' ';
-                   json_off++) ;
-               /* Verify for end of object boundary */
-               if (json_str.charAt(json_off) == '}') {
-                       json_off++;
-                       return true;
-               }
-               /* Parse key name */
-               key = '';
-               for (; json_off < json_len &&
-                   json_str.charAt(json_off) != ':' &&
-                   json_str.charAt(json_off) != ' ';
-                   json_off++)
-                       key += json_str.charAt(json_off);
-               /* Skip spaces */
-               for (; json_off < json_len &&
-                   json_str.charAt(json_off) == ' ';
-                   json_off++) ;
-               if (json_str.charAt(json_off) != ':') {
-                       json_error = ': expected after object member name';
-                       return false;
-               }
-               json_off++;
-               /* Strip possible " around key name */
-               if (key.length > 1 && key.substr(0, 1) == '"' &&
-                   s.substr(key.length - 1, 1) == '"')
-                       key = key.substr(1, key.length - 2);
-               if (key.length < 1) {
-                       json_error = 'Object member name missing';
-                       return false;
-               }
-               /* Fill object element */
-               o[key] = json_parse_r();
-               /* Skip spaces */
-               for (; json_off < json_len &&
-                   json_str.charAt(json_off) == ' ';
-                   json_off++) ;
-               /* Expect separator or end of object boundary */
-               if (json_str.charAt(json_off) == '}')
-                       continue;
-               if (json_str.charAt(json_off) == ',') {
-                       json_off++;
-                       continue;
-               }
-               json_error = 'Unexpected end of object element separator';
-               return false;
-       }
-
-       json_error = 'End of string reached';
-       return false;
-}
-
-function json_parse_array(o)
-{
-       /* Skip spaces */
-       for (; json_off < json_len &&
-           json_str.charAt(json_off) == ' ';
-           json_off++) ;
-       /* Make sure we start with '[' */
-       if (json_str.charAt(json_off) != '[') {
-               json_error = '[ expected to start an Array object';
-               return false;
-       }
-       json_off++;
-
-       for (; json_off < json_len; ) {
-               /* Skip spaces */
-               for (; json_off < json_len &&
-                   json_str.charAt(json_off) == ' ';
-                   json_off++) ;
-               /* Verify for end of array object boundary */
-               if (json_str.charAt(json_off) == ']') {
-                       json_off++;
-                       return true;
-               }
-               /* Fill array element */
-               o.push(json_parse_r());
-               /* Skip spaces */
-               for (; json_off < json_len &&
-                   json_str.charAt(json_off) == ' ';
-                   json_off++) ;
-               /* Expect separator or end of array object boundary */
-               if (json_str.charAt(json_off) == ']')
-                       continue;
-               if (json_str.charAt(json_off) == ',') {
-                       json_off++;
-                       continue;
-               }
-               json_error = 'Unexpected end of array element separator';
-               return false;
-       }
-
-       json_error = 'End of string reached';
-       return false;
-}
diff --git a/mmsoftware/js/jslib/ml_clean.js b/mmsoftware/js/jslib/ml_clean.js
deleted file mode 100644 (file)
index 2b13636..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/* $Id: ml_clean.js,v 1.1 2006/08/06 12:11:23 mmondor Exp $ */
-
-/*
- * Copyright (C) 2004-2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-/*
- * Useful object to use for HTML tags.  <tab> consists of tag name, and
- * <close> of a boolean specifying of the tag requires a corresponding closing
- * tag (i.e. <p>[body]</p>.  Attributes and body elements may be added after
- * creating such an object, and toStr() used to obtain the actual HTML result.
- */
-function MLTag(tag, close)
-{
-       /*
-        * MLTag object properties
-        */
-       this.tag = tag;
-       this.close = close;
-       this.attributes = {};   /* Object with associative attributes */
-       this.contents = [];     /* Array object */
-}
-
-/*
- * Define prototype of the MLTag object.
- */
-MLTag.prototype = {
-       /* A string of spaces to be used for indenting */
-       indent_str: '                                        ' +
-           '                              ',
-
-       /*
-        * Wraps specified string at 70 columns and observing specified
-        * indentation level
-        */
-       wrap: function(str, level)
-       {
-               var len = str.length;
-               var newstr = this.indent_str.substr(0, level);
-               var newlen = level;
-
-               /*
-                * Could find index to space and use substring as necessary
-                * instead of looping through every character.  Of course,
-                * this could also all be implemented using C native code.
-                */
-               for (var i = 0; i < len; i++) {
-                       var c = str.charAt(i);
-
-                       if (c == ' ' && newlen > 70) {
-                               newstr += "\n" + this.indent_str.substr(0,
-                                   level);
-                               newlen = level;
-                               continue;
-                       }
-                       newstr += c;
-                       newlen++;
-               }
-
-               return newstr;
-       },
-
-       /*
-        * Add specified attribute with optional associated value to this tag
-        */
-       addAttr: function(attr, value)
-       {
-
-               this.attributes[attr] = value;
-       },
-
-       /*
-        * Add arbitrary content in sequencial order to this tag's body
-        */
-       addContent: function(item)
-       {
-
-               this.contents.push(item);
-       },
-
-       /*
-        * Returns a string consisting of this tag along with its body and
-        * optional corresponding closing tag
-        */
-       toStr: function(level)
-       {
-               var str = '';
-
-               /* Null tags may exist as containers */
-               if (this.tag != null) {
-
-                       /* Open opening tag */
-                       str += this.indent_str.substr(0, level) + '<' +
-                           this.tag;
-
-                       /*
-                        * Store these immediately for performance since we
-                        * use those values several times later on, also
-                        * saves typing
-                        */
-                       var taglen = this.tag.length;
-                       var len = level + taglen + 1;
-                       var attributes = this.attributes;
-
-                       /*
-                        * Add each of our attributes with their optional
-                        * values
-                        */
-                       for (var attr in attributes) {
-                               var value;
-
-                               if (len > 70) {
-                                       len = level + taglen + 1;
-                                       str += "\n" +
-                                           this.indent_str.substr(0, len);
-                               }
-                               str += ' ' + attr;
-                               len += taglen + 1;
-                               if ((value = attributes[attr]) != null) {
-                                       str += '="' + value + '"';
-                                       len += value.length + 3;
-                               }
-                       }
-
-                       /* Close opening tag */
-                       str += ">\n";
-
-                       /* Increase our indent level for content */
-                       level++;
-
-               }
-
-               /*
-                * Now add all our contents, if any, which may consist of
-                * other MLTag objects or arbitrary String objects.  Use
-                * recursion to process MLTag ones, which may also have their
-                * respective bodies and closing tags.
-                */
-               for (var i in this.contents) {
-                       var a = this.contents[i];
-
-                       if (typeof a == 'object')
-                               str += a.toStr(level);
-                       else
-                               str += this.wrap(a, level) + "\n";
-               }
-
-               /*
-                * If this tag required closing, do so
-                */
-               if (this.tag != null) {
-                       level--;
-                       if (this.close)
-                               str += this.indent_str.substr(0, level) +
-                                   '</' + this.tag + ">\n";
-               }
-
-               return str;
-       }
-}
-
-
-var entitites_table = {
-       '<': '&lt;',
-       '>': '&gt;',
-       '&': '&amp;',
-       '"': '&quot;',
-       "`": '&lsquo;',
-       "'": '&rsquo;'
-};
-
-/*
- * Function to convert a supplied string to use HTML/SGML special entitites.
- * This also allows HTML escaping from user-supplied strings.
- */
-function toHTMLEntities(str)
-{
-       var s = '';
-       var i, t, c, e;
-
-       for (i = 0, t = str.length; i < t; i++) {
-               c = str.charAt(i);
-               if ((e = entitites_table[c]) != undefined)
-                       s += e;
-               else
-                       s += c;
-       }
-
-       return s;
-}
diff --git a/mmsoftware/js/jslib/ml_machine.js b/mmsoftware/js/jslib/ml_machine.js
deleted file mode 100644 (file)
index 4101539..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/* $Id: ml_machine.js,v 1.1 2006/08/06 12:11:23 mmondor Exp $ */
-
-/*
- * Copyright (C) 2004-2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-/*
- * Useful object to use for HTML tags.  <tab> consists of tag name, and
- * <close> of a boolean specifying of the tag requires a corresponding closing
- * tag (i.e. <p>[body]</p>.  Attributes and body elements may be added after
- * creating such an object, and toStr() used to obtain the actual HTML result.
- */
-function MLTag(tag, close)
-{
-       /*
-        * MLTag object properties
-        */
-       this.tag = tag;
-       this.close = close;
-       this.attributes = {};   /* Object with associative attributes */
-       this.contents = [];     /* Array object */
-}
-
-/*
- * Define prototype of the MLTag object.
- */
-MLTag.prototype = {
-
-       /*
-        * Add specified attribute with optional associated value to this tag
-        */
-       addAttr: function(attr, value)
-       {
-
-               this.attributes[attr] = value;
-       },
-
-       /*
-        * Add arbitrary content in sequencial order to this tag's body
-        */
-       addContent: function(item)
-       {
-
-               this.contents.push(item);
-       },
-
-       /*
-        * Returns a string consisting of this tag along with its body and
-        * optional corresponding closing tag
-        */
-       toStr: function(level)
-       {
-               var str = '';
-
-               /* Null tags may exist as containers */
-               if (this.tag != null) {
-
-                       /* Open opening tag */
-                       str += '<' + this.tag;
-
-                       /*
-                        * Store these immediately for performance since we
-                        * use those values several times later on, also
-                        * saves typing
-                        */
-                       var taglen = this.tag.length;
-                       var len = taglen + 1;
-                       var attributes = this.attributes;
-
-                       /*
-                        * Add each of our attributes with their optional
-                        * values
-                        */
-                       for (var attr in attributes) {
-                               var value;
-
-                               str += ' ' + attr;
-                               len += taglen + 1;
-                               if ((value = attributes[attr]) != null) {
-                                       str += '="' + value + '"';
-                                       len += value.length + 3;
-                               }
-                       }
-
-                       /* Close opening tag */
-                       str += ">";
-
-               }
-
-               /*
-                * Now add all our contents, if any, which may consist of
-                * other MLTag objects or arbitrary String objects.  Use
-                * recursion to process MLTag ones, which may also have their
-                * respective bodies and closing tags.
-                */
-               for (var i in this.contents) {
-                       var a = this.contents[i];
-
-                       if (typeof a == 'object')
-                               str += a.toStr(0);
-                       else
-                               str += a;
-               }
-
-               /*
-                * If this tag required closing, do so
-                */
-               if (this.tag != null && this.close)
-                       str += '</' + this.tag + ">";
-
-               return str;
-       }
-
-}
-
-
-var entitites_table = {
-       '<': '&lt;',
-       '>': '&gt;',
-       '&': '&amp;',
-       '"': '&quot;',
-       "`": '&lsquo;',
-       "'": '&rsquo;'
-};
-
-/*
- * Function to convert a supplied string to use HTML/SGML special entitites.
- * This also allows HTML escaping from user-supplied strings.
- */
-function toHTMLEntities(str)
-{
-       var s = '';
-       var i, t, c, e;
-
-       for (i = 0, t = str.length; i < t; i++) {
-               c = str.charAt(i);
-               if ((e = entitites_table[c]) != undefined)
-                       s += e;
-               else
-                       s += c;
-       }
-
-       return s;
-}
diff --git a/mmsoftware/js/jslib/pgsql.js b/mmsoftware/js/jslib/pgsql.js
deleted file mode 100644 (file)
index 023b037..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* $Id: pgsql.js,v 1.1 2006/08/06 11:58:11 mmondor Exp $ */
-
-/*
- * Copyright (C) 2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Utility functions added to the postgresql access objects
- */
-
-
-PGResult.prototype.jsGetResults = function()
-{
-       var rows = this.nTuples();
-       var cols = this.nFields();
-
-       var columns = [];
-       for (col = 0; col < cols; col++)
-               columns.push(this.fName(col));
-
-       var results = [];
-       for (row = 0; row < rows; row++) {
-               var o = {};
-
-               for (col = 0; col < cols; col++)
-                       o[columns[col]] = this.getValue(row, col);
-               results.push(o);
-       }
-       this.clear();
-
-       return results;
-}
-
-PGConn.prototype.jsExecParams = function(q, args)
-{
-       return this.execParams(q, args.length, null, args, null, null, 0);
-}
-
-PGConn.prototype.jsPrepare = function(name, query)
-{
-       return this.prepare(name, query, 0, null);
-}
-
-PGConn.prototype.jsExecPrepared = function(name, args)
-{
-       return this.execPrepared(name, args.length, args, null, null, 0);
-}
diff --git a/mmsoftware/js/jslib/root.js b/mmsoftware/js/jslib/root.js
deleted file mode 100644 (file)
index 58f9fe7..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/* $Id: root.js,v 1.1 2006/08/06 12:11:23 mmondor Exp $ */
-
-/*
- * Copyright (C) 2005-2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Implementation of a virtual chroot(2) system.
- */
-
-
-
-const PATH_MAX = 255;
-
-
-
-function Root(root)
-{
-
-       if (!(this.root = this.valid_path(root)))
-               throw('Invalid root path "' + root + '"!');
-       this.cwd = '/';
-}
-
-Root.prototype = {
-
-       /*
-        * Quick lookup table of valid characters within pathnames.
-        * Currently 'a'-'z', 'A'-'Z', '0'-'9', '.', '/', '-', '_'
-        */
-       valid_char_table: [
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
-               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
-               0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
-               0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-       ],
-
-       /*
-        * Base function to return formatted valid path, or false.
-        * Returned path will always begin with '/' and not have any
-        * trailing '/'.  Multiple '/' are also collapsed into one.
-        */
-       valid_path: function(path)
-       {
-               var i, t, l, p, c, code;
-
-               p = l = '/';
-               for (i = 0, t = path.length; i < t; i++) {
-                       c = path.charAt(i);
-                       if (l == '/') {
-                               /* Collapse multiple '/' */
-                               if (c == '/')
-                                       continue;
-                               /* Prohibit '.' at start of element */
-                               if (c == '.')
-                                       return false;
-                       }
-                       /* Validate chars */
-                       code = c.charCodeAt(0);
-                       if (code != code & 0xff || 
-                           this.valid_char_table[code] == 0)
-                               return false;
-                       p += c;
-                       l = c;
-               }
-               /* Strip last '/' if any, unless only one */
-               if (c == '/' && p.length > 1)
-                       p = p.substr(0, p.length - 1);
-
-               /* If exceeding PATH_MAX, return false */
-               if (p.length > PATH_MAX)
-                       return false;
-
-               return p;
-       },
-
-       /*
-        * Returns version of provided path which points to the parent
-        * directory if possible.  Returns false otherwise.
-        * Should only be used with paths first copied using valid_path().
-        * Can typically be used with the cwd.
-        */
-       parent: function(path)
-       {
-               var i;
-
-               /* First make sure that path starts with '/' */
-               if (path.length < 2 || path.charAt(0) != '/')
-                       return false;
-
-               /* Strip trailing '/' chars */
-               for (i = path.length - 1; i >= 0 && path.charAt(i) == '/';
-                   i--) ;
-               if (i <= path.length)
-                       path = path.substr(0, i + 1);
-
-               /*
-                * Locate previous '/', strip everything after it, including
-                * it, except in the case where it is the only remaining,
-                * where path must remain '/'.
-                */
-               if ((i = path.lastIndexOf('/')) == 0)
-                       i = 1;
-               return path.substring(0, i);
-       },
-
-       /*
-        * This function should always be called when processing user-supplied
-        * paths.  The application should then only trust the object it
-        * returns.  Returns false if the path is invalid.
-        * Otherwise, returns an object, with the following properties:
-        *
-        * <real>       System-wide absolute real fullpath, to be used by the
-        *              application to access the files/directories in
-        *              question.
-        * <virtual>    Virtual root based absolute fullpath, useful to report
-        *              to the user.  Can also be useful to change a Root
-        *              object's cwd to, after verifying that <real> really
-        *              points to an existing directory.
-        */
-       valid_virtual: function(path)
-       {
-               var cwd, c, l, t, o;
-
-               o = {};
-               cwd = this.cwd;
-
-               /*
-                * Look for '~', or '/' in the beginning of the path,
-                * in which case cwd gets cleared to '/'.  Also look for
-                * './' or '.[EOS]', which we simply skip, meaning the
-                * current directory.
-                */
-               if ((l = path.length) > 0) {
-                       c = path.charAt(0);
-                       if (c == '~' || c == '/') {
-                               cwd = '/';
-                               path = path.substr(1);
-                       } else if (c == '.') {
-                               if (l == 1)
-                                       path = '';
-                               else if (l > 1 && path.charAt(1) == '/')
-                                       path = path.substr(2);
-                       }
-               }
-
-               /*
-                * Now process all starting '..' or '../', modifying cwd if
-                * allowed, and stripping them from path.  In case of '../',
-                * also strip any multiple '/'.
-                */
-               for (;;) {
-                       t = false;
-                       l = path.length;
-                       if ((l == 2 && path == '..') ||
-                           (l > 2 && path.substr(0, 2) == '..' &&
-                           (t = (path.charAt(2) == '/')))) {
-                               if (!(cwd = this.parent(cwd)))
-                                       return false;
-                               if (t) {
-                                       for (i = 2; path.charAt(i) == '/';
-                                           i++) ;
-                                       path = path.substr(i);
-                                       continue;
-                               } else {
-                                       path = path.substr(2);
-                                       continue;
-                               }
-                       }
-                       break;
-               }
-
-               /*
-                * Now attempt to fill in our object properties.
-                * this.valid_path() performs necessary sanity checking.
-                */
-               if (!(o.virtual = this.valid_path('/' + cwd + '/' + path)))
-                       return false;
-               o.real = this.root + o.virtual;
-
-               return o;
-       }
-
-};
diff --git a/mmsoftware/js/jslib/string.js b/mmsoftware/js/jslib/string.js
deleted file mode 100644 (file)
index b8affc2..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* $Id: string.js,v 1.1 2006/08/06 11:58:11 mmondor Exp $ */
-
-/*
- * Copyright (C) 2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Extension to the standard String object to support startsWith() and
- * endsWith() very useful methods.
- */
-
-
-
-String.prototype.startsWith = function(str)
-{
-       var t = str.length;
-
-       if (this.length >= t && this.substr(0, t) == str)
-               return true;
-
-       return false;
-}
-
-String.prototype.endsWith = function(str)
-{
-       var t1 = str.length;
-       var t2 = this.length;
-
-       if (t2 >= t1 && this.substr(t2 - t1, t1) == str)
-               return true;
-
-       return false;
-}
diff --git a/mmsoftware/js/util/spidermonkey-config b/mmsoftware/js/util/spidermonkey-config
deleted file mode 100755 (executable)
index 359d2d0..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/sh
-#
-# $Id: spidermonkey-config,v 1.1 2006/07/22 04:36:16 mmondor Exp $
-#
-# Configure script to help build scripts
-# by Matthew Mondor
-
-CFLAGS='-I/usr/local/spidermonkey/include -DXP_UNIX'
-LDFLAGS='-Wl,-R/usr/local/spidermonkey/lib -L/usr/local/spidermonkey/lib -ljs'
-
-DLDFLAGS='-Wl,-R/usr/local/spidermonkey/lib -L/usr/local/spidermonkey/lib -ljs_dbg'
-
-VERSION='SpiderMonkey 1.5-rc6A'
-
-usage()
-{
-       echo
-       echo 'Usage: spidermonkey-config [-v] [-c] [-l] [-d]'
-       echo
-       echo ' -v : Shows SpiderMonkey version'
-       echo ' -c : Shows flags suitable to append to $CFLAGS'
-       echo ' -l : Shows flags suitable to append to $LDFLAGS'
-       echo ' -d : Shows debugging versions of the flags'
-       echo
-}
-
-if [ -z $@ ]; then
-       usage
-       exit 0
-fi
-
-while getopts dclv c; do
-       case $c in
-       d)
-               LDFLAGS="$DLDFLAGS"
-               ;;
-       c)
-               echo $CFLAGS
-               ;;
-       l)
-               echo $LDFLAGS
-               ;;
-       v)
-               echo $VERSION
-               ;;
-       *)
-               usage
-               exit 0
-               ;;
-       esac
-done
diff --git a/mmsoftware/make.sh b/mmsoftware/make.sh
deleted file mode 100755 (executable)
index 95d71ce..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/sh
-# $Id: make.sh,v 1.2 2003/07/02 17:20:52 mmondor Exp $
-
-. mmlib/makefuncs.sh
-
-cd mmlib/
-clean mmlib
-makebin mmlib
-cd ../
-
-cd mmpasswd/
-clean mmpasswd
-makebin mmpasswd
-cd ../
-
-cd mmstatd/src/
-clean mmstatd
-makebin mmstatd
-cd ../../
-cd apache-mmstat/
-clean apache-mmstat
-makebin apache-mmstat
-cd ../
-
-cd mmftpd/src/
-clean mmftpd
-makebin mmftpd
-cd ../../
-
-cd mmmail/src/mmsmtpd/
-clean mmsmtpd
-makebin mmsmtpd
-cd ../mmpop3d
-clean mmpop3d
-makebin mmpop3d
-cd ../../
-
-echo
-echo 'You may now ./install.sh help or ./install.sh to install/upgrade'
-echo
diff --git a/mmsoftware/mmanoncvs/GNUmakefile b/mmsoftware/mmanoncvs/GNUmakefile
deleted file mode 100644 (file)
index 817ce65..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-# $Id: GNUmakefile,v 1.5 2004/05/31 03:58:36 mmondor Exp $
-
-MMLIBS := $(addprefix ../mmlib/,mmpool.o mmlog.o mmreadcfg.o mmstring.o \
-mmhash.o)
-
-OBJS := mmanoncvs.o
-
-CFLAGS += -Wall
-
-
-all: mmanoncvs
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I../mmlib -o $@ $<
-
-mmanoncvs: $(MMLIBS) $(OBJS)
-       cc -o $@ $(OBJS) -lc $(MMLIBS)
-
-install: all
-       install -cs -o 0 -g 0 -m 555 mmanoncvs /usr/local/sbin
-       install -c -o 0 -g 0 -m 444 mmanoncvs.conf.5 /usr/local/man/man5
-       install -c -o 0 -g 0 -m 444 mmanoncvs.list.5 /usr/local/man/man5
-       install -c -o 0 -g 0 -m 444 mmanoncvs.8 /usr/local/man/man8
-
-clean:
-       rm -f mmanoncvs $(OBJS) $(MMLIBS)
diff --git a/mmsoftware/mmanoncvs/mmanoncvs.8 b/mmsoftware/mmanoncvs/mmanoncvs.8
deleted file mode 100644 (file)
index 6acfad1..0000000
+++ /dev/null
@@ -1,720 +0,0 @@
-.\" $Id: mmanoncvs.8,v 1.10 2004/10/01 15:26:21 mmondor Exp $
-.\"
-.\" Copyright (C) 2003-2004, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\" 5. Redistribution of source code may not be released under the terms of
-.\"    any GNU Public License derivate.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd November 9, 2003
-.Dt MMANONCVS 8
-.Os mmsoftware
-.Sh NAME
-.Nm mmanoncvs
-.Nd
-Companion to
-.Xr mmspawnd 8
-to offer secure public CVS read-only pserver access
-.Sh SYNOPSIS
-.Nm mmanoncvs Op Fl f Ar <config_file>
-.Sh DESCRIPTION
-.Nm
-was written to allow providing a common CVS pserver for various CVS
-repositories maintained by different people (or projects) on the same
-server. Offering pserver access is important for many opensource projects.
-This utility provides a safe and comfortable way to create and update a
-single read-only repository (which will usually be accessed as /cvsroot
-from a pserver user standpoint), while allowing space for a number of
-independent repositories pertaining to various users or projects, merging
-them in the read-only mirror.
-.Pp
-Support is implemented for CVS-friendly read access locking when creating
-a backup of a CVS repository, so that CVS concurrency is allowed. For instance,
-a user may be commiting changes to the repository while the cron event
-scheduler runs
-.Xr mmanoncvs 8
-to back it up to read-only storage. Both will then behave properly and the
-repository will remain consistent for the public users.
-.Pp
-Another type of synchronization was also implemented, so that while replacing
-the previous pserver backup with the new one it appears atomic to the pserver
-users. This is done via the special
-.Xr mmspawnd 8
-.Nm ALOCK
-support.
-.Pp
-In practice, this software is best used with a corresponding
-.Xr mmspawnd 8
-setup providing safe read-only CVS pserver support under a
-.Xr chroot 2
-environment. It however can be used standalone.
-.Pp
-A special effort was made so that it be safe to run
-.Nm
-by the superuser. It can however also be ran from an unprivileged user,
-or can alternatively revoke privileges to a normal one after launching
-by the superuser, providing that the user has the required access to
-.Nm REPDIR
-and
-.Nm TMPDIR ,
-to the source repositories if
-.Nm CVS_LOCKING
-is enabled, and to
-.Nm ALOCK_PATH
-if
-.Nm ALOCK_LOCKING
-is enabled.
-.Pp
-When the need to recursively delete directory trees (I.E. to delete the
-contents of the old copy after successful replacement, to delete temporary
-files), a safe method is used so that only wanted files are deleted, and
-that recursion be limited to
-.Nm MAX_RECURSE .
-Special care is done to not be able to be redirected out of the wanted
-directory via a symbolic link.
-.Pp
-When performing a backup from an administrator-specified directory,
-special care is done to prevent abnormally high recursion levels,
-and to only copy valid RCS files and CVS directories, while setting
-their permissions appropriately on the destination repository. We
-do not process special files, including symbolic links, and are logging
-the event to stderr (which will usually result in being mailed to the
-administrator by the cron event scheduler). Nothing is ouput if everything
-is successful.
-.Pp
-When performing backups, if any of the administrator specified elements in
-.Xr mmanoncvs.list 5
-fails, we abort the backup, free any held locks, delete temporary files and
-leave the last successful destination repository as-is, to prevent common
-errors from disabling correct public pserver access. We however also log
-such problems to stderr.
-.Pp
-The CVSROOT directory is automatically written in the destination repository
-copy to not be available via CVS checkout, and to have the right options for
-use with
-.Xr mmspawnd 8
-and
-.Xr cvs 1
-pserver in read-only mode.
-.Sh INSTRUCTIONS TO SETUP WITH MMSPAWND(8)
-.Ss Group and user(s) creation
-.Bl -tag -width indent -offset indent
-.It Nm Creating the 'anoncvs' group
-The
-.Xr cvs 1
-command has special requirements to function, even in pserver mode.
-This group will allow it write access to the '/cvsroot/CVSROOT/val-tags',
-as well as to the '/tmp' directory where it will create its CVS read access
-locks, and to '/dev/null'. It will also allow it read-only access to
-everything in '/cvsroot'.
-.It Nm Creating the unprivileged pserver administrator user
-This step is necessary if
-.Xr mmanoncvs 8
-will not run as the superuser. This would then generally consist of a disabled
-user, without a valid shell, with the home directory set to '/var/anoncvs'.
-This user should be part of the previously created 'anoncvs'
-group. A typical name for this user is 'anoncvsa'.
-.Pp
-Note that when not running
-.Xr mmanoncvs 8
-as the superuser, special care must be taken for permissions. See the
-.Xr mmanoncvs.conf 5
-manual page about the
-.Nm DROP_PRIVS ,
-.Nm USER ,
-.Nm GROUPS ,
-.Nm ALOCK_LOCKING
-and
-.Nm CVS_LOCKING
-configuration parameters for more details.
-.El
-.Ss Root directory setup for pserver with mmspawnd(8)
-Note that most of the files and directories here are created using a
-.Xr umask 2
-of 227. You however will need to use the
-.Xr chown 8
-and
-.Xr chmod 8
-commands at several occasions.
-.Bl -tag -width indent -offset indent
-.It Nm Creating the alternate root directory for chroot(2)
-The new alternate root directory should be created, typically
-.Nm /var/anoncvs .
-This file should be owned by the pserver repository administrator user
-(the user under which permissions runs
-.Xr mmanoncvs 8 ) .
-The group of this directory should be set to the previously created 'anoncvs'
-group. The mode of this directory should be 750.
-.It Nm Creation of the '/dev/null' device
-.Xr cvs 1
-requires this device to exist. Thus, the
-.Nm /var/anoncvs/dev
-directory should be created, of 'root' owner, 'anoncvs' group, and mode 550.
-Then the
-.Nm /var/anoncvs/dev/null
-special character device file should be created, of owner 'root',
-group 'anoncvs', mode 660. This can be done using the
-.Xr mknod 8
-command. The major and minor device numbers for it are operating system
-dependent. You can verify by looking at your
-.Nm /dev/null
-file with the
-.Xr ls 1
-command and -l option.
-.It Nm Installing the cvs(1) command into the new root
-The
-.Nm /var/anoncvs/bin
-directory should first be created, of owner 'root', group 'anoncvs', mode 550.
-The cvs command should then be copied as
-.Nm /var/anoncvs/bin/cvs ,
-with owner 'root', group 'anoncvs', mode 550.
-Note that
-.Xr mmspawnd 8
-will only allow to execute ELF format binaries. Also, it is recommended to use
-a statically linked executable for both simplicity and efficiency.
-.Pp
-If using a dynamicly linked executable, additional directories and files
-will need to be created, like directories:
-.Nm /var/anoncvs/lib ,
-.Nm /var/anoncvs/usr ,
-.Nm /var/anoncvs/etc ,
-and
-.Nm /var/anoncvs/libexec
-of owner 'root', group 'anoncvs', mode 550,
-and system executable
-.Nm /usr/libexec/ld.elf_so
-copied as
-.Nm /var/anoncvs/libexec/ld.elf_so
-and set to owner 'root', group 'anoncvs' and mode 550.
-It may also be necessary to create
-.Nm /var/anoncvs/etc/ld.so.conf
-of owner 'root', group 'anoncvs', mode 440, with a single line in it:
-.Bd -literal -offset indent
-/lib
-.Ed
-.Pp
-The libraries required by
-.Xr cvs 1
-should then be verified using the
-.Xr ldd 1
-command, and each of the required libraries copied into
-.Nm /var/anoncvs/lib/ ,
-with owner 'root', group 'anoncvs', mode 440.
-Note that the requirements for dynamic loading are system-dependent and vary;
-One of the many reasons to choose a statically linked ELF executable,
-as opposed to a dynamically linked ELF executable for this.
-.It Nm Allowing cvs(1) to map 'anoncvs' user/group
-Now that we created the 'anoncvs' user and group for the current system,
-it is also necessary to make them map to the same IDs (identification numbers)
-from within the new root after
-.Xr chroot 2 .
-Although this is also system-dependent, I will show some example which was
-tested to work on BSD. I will also add notes for Linux-specific requirements.
-.Pp
-To allow the groups to map, first ensure that the
-.Nm /var/anoncvs/etc
-directory is created, of owner 'root', group 'anoncvs', mode 550.
-You then should create the
-.Nm /var/anoncvs/etc/group
-file, of owner 'root', group 'anoncvs', mode 440.
-This file will generally only map two groups: 'wheel' (or 'root' on Linux),
-and 'anoncvs', as follows:
-.Bd -literal -offset indent
-wheel:*:0:
-anoncvs:*:1017:
-.Ed
-.Pp
-Note that the 'wheel' name may be replaced by 'root' on Linux if desired.
-The ID for that group will always be 0 on any unix. However, the 'anoncvs'
-group ID (1017 in this example) should correspond to the ID of your
-own 'anoncvs' group, as shown in
-.Nm /etc/group .
-.Pp
-We then also want the 'root' and 'anoncvs' users to map properly for the
-new root. On NetBSD, this can be achieved easily using the
-.Xr vipw 8
-command with the
-.Nm -d/var/anoncvs
-parameter. An example of the lines to type in follows:
-.Bd -literal -offset indent
-root:*:0:0::0:0::/:/notexists
-anoncvs:*:1012:1017::0:0::/cvsroot:/notexists
-anoncvsa:*:1013:1017::0:0::/:/notexists
-.Ed
-.Pp
-This above example maps user 'root' to ID 0, which will be the case on
-any unix. The 'anoncvs' and 'anoncvsa' should however have their UID
-(User ID) and GID (primary Group ID) set to the ones matching the rest
-of your system. This would normally create the following files in
-.Nm /var/anoncvs/etc .
-You can then ensure that they are set to the proper permissions:
-.Nm passwd ,
-.Nm pwd.db :
-user 'root', group 'anoncvs', mode 440.
-.Nm master.passwd ,
-.Nm spwd.db :
-user 'root', group 'anoncvs', mode 400.
-Obviously, the 'anoncvsa' user is only required if it was chosen to
-run
-.Xr mmanoncvs 8
-as an unprivileged user.
-.Pp
-On Linux, creating the files
-.Nm /var/anoncvs/etc/passwd
-of owner 'root', group 'anoncvs', mode 440 and
-.Nm /var/anoncvs/etc/shadow
-of owner 'root', group 'anoncvs', mode 400
-should be done instead of running
-.Xr vipw 8 .
-An example contents for
-.Nm passwd :
-.Bd -literal -offset indent
-root:*:0:0::/:/notexists
-anoncvs:*:1012:1017::/cvsroot:/notexists
-anoncvsa:*:1013:1017::/:/notexists
-.Ed
-.Pp
-And for
-.Nm shadow :
-.Bd -literal -offset indent
-root:*:0:0:10000::::
-anoncvs:*:0:0:10000::::
-anoncvsa:*:0:0:10000::::
-.Ed
-.Pp
-Note that if using glibc, it appears to require to be able to dynamically
-load some parts of it even in a static executable. This means that the
-libc library will also need to be present under the alternate root's
-.Nm /lib
-directory. Moreover, it appears to also require the
-.Nm libnss_dns
-and
-.Nm libnss_files
-dynamic libraries (at least on debian). This also means that the
-.Nm ld-linux.so
-library is required as well. This is unfortunate and for this reason it
-might not be harder to use a fully dynamically linked
-.Xr cvs 1
-when using glibc. If you are using Linux and want to have a statically linked
-version without needing external libraries, you will most probably need to
-use another libc library to build it, such as
-.Nm diet-libc
-or
-.Nm uclibc .
-.It Nm The temporary working directory
-It is now necessary to create the temporary working directory which will
-be used both by
-.Xr cvs 1
-for the read lock files and for
-.Xr mmanoncvs 8
-to create temporary mirror backups before replacing the official mirror
-on success. It is thus necessary to create the
-.Nm /var/anoncvs/tmp
-directory of owner 'root', group 'anoncvs', and mode 770.
-The
-.Nm TMPDIR
-parameter in
-.Xr mmanoncvs.conf 5
-will be set to this directory.
-.It Nm The actual public CVS pserver repository root
-This is the actual mirror, which is maintained by
-.Xr mmanoncvs 8
-and corresponds to the
-.Nm REPDIR
-parameter of
-.Xr mmanoncvs.conf 5 .
-This is also the
-.Nm /cvsroot
-directory as seen by CVS pserver users. The
-.Nm /var/anoncvs/cvsroot
-directory should be created. It's owner should correspond to the one under
-which
-.Xr mmanoncvs 8
-is set to execute it's tasks. In practive, this usually means 'root' owner
-or 'anoncvsa' owner. It's group should be 'anoncvs', and it's mode 750.
-Please see the
-.Xr mmanoncvs.conf 5
-manual page for more information about the issues involved in using an
-unprivileged user.
-.It Nm Additional tips and tricks
-It is possible on NetBSD to use the NULLFS filesystem to mount various
-directories of arbitrary filesystems into the wanted locations of the new
-.Nm /var/anoncvs
-root (and the noexec flag can be used). This can allow for instance to have
-a system mounted with the noexec flag, except for /bin where
-.Xr cvs 1
-resides. On most unix systems, alternatives can be used using real filesystems
-to achieve the same results.
-.Xr mmanoncvs 8 ,
-if allowed to keep the executable bit on files when copying using the
-.Nm KEEP_EXEC
-parameter in
-.Xr mmanoncvs.conf 5 ,
-ensures to only set the executable bit of the owner of the files.
-However, if a new
-.Xr cvs 1
-vulnerability was discovered which allowed to upload arbitrary files into
-.Nm /var/anoncvs/tmp
-(the only directory
-.Xr mmspawnd 8
-allow it arbitrary write access), it would be nice to have a noexec
-.Nm /tmp .
-.Pp
-If enabling hostname resolution in
-.Xr mmspawnd 8 ,
-it might be necessary to create the
-.Nm /var/anoncvs/resolv.conf
-file of owner 'root', group 'anoncvs' and mode 440, and to specify the
-IP addresses of the DNS servers in it. Otherwise hostname resolution will
-fail on many systems using the
-.Xr bind 3
-libraries.
-.El
-.Ss Example configuration files
-Because
-.Xr mmspawnd 8
-and
-.Xr mmanoncvs 8
-depend on eachother, it is a good idea to show a few example configuration
-files which were used successfully for particular setups. Here is a setup
-to run
-.Xr mmspawnd 8
-as unprivileged user 'anoncvs' (which should always be done), and to run
-.Xr mmanoncvs 8
-via a cron event as root, to drop privileges to user 'anoncvsa' (which
-requires write access to the directories to copy, thus adding the 'cvs'
-group in
-.Nm GROUPS ) .
-A simpler setup is to run
-.Xr mmanoncvs 8
-as the superuser from a cron event setting
-.Nm DROP_PRIVS
-to FALSE. If an existing, enabled unprivileged user wants to run it
-as a cron event,
-.Nm DROP_PRIVS
-should be FALSE, and the user should have the necessary write permissions
-to the source repository(ies), as well as access to lock the
-.Nm ALOCK_PATH .
-See the
-.Xr mmanoncvs.conf 5
-and
-.Xr mmspawnd.conf 5
-manual pages for details.
-.Bl -tag -width indent -offset indent
-.It Nm /usr/local/etc/mmspawnd-anoncvs.conf
-.Bd -literal -offset left
-# See mmspawnd.conf(5) manual page for more information
-# and default values
-
-PID_PATH       /var/run/mmspawnd-anoncvs.pid
-LOCK_PATH      /var/run/mmspawnd-anoncvs.lock
-
-# The following lock is useful for mmanoncvs(8)
-ALOCK_PATH     /var/run/mmspawnd-anoncvs.alock
-# root if mmanoncvs(8) DROP_PRIVS=FALSE
-ALOCK_USER     anoncvsa  # ^
-ALOCK_GROUP    anoncvs
-ALOCK_MODE     400
-
-USER           anoncvs
-GROUPS         anoncvs
-
-CHROOT_DIR     /var/anoncvs
-
-PROCTITLE      "CVS pserver"
-LISTEN_PORT    2401
-COMMAND        "/bin/cvs -z6 -f --allow-root=/cvsroot pserver"
-
-RESOLVE_ADDRESSES      FALSE
-
-KILL_CHILDREN  FALSE
-
-# Note: It is generally a bad idea to kill cvs while it
-# runs (since it holds lock files). So we set these limits
-# but put them high enough to not interfere with normal CVS
-# operation.
-COMMAND_TIMEOUT        1200
-RLIMITS                TRUE
-RLIMIT_CORE    0
-RLIMIT_CPU     1200
-.Ed
-.It Nm /usr/local/etc/mmanoncvs.conf
-.Bd -literal -offset left
-DROP_PRIVS             TRUE
-USER                   anoncvsa
-GROUPS                 anoncvs,cvs
-REPGROUP               anoncvs
-
-LOCK_PATH              /var/run/mmanoncvs.lock
-ALOCK_LOCKING          TRUE
-ALOCK_PATH             /var/run/mmspawnd-anoncvs.alock
-CVS_LOCKING            TRUE
-CVS_LOCK_DELAY         30
-CVS_LOCK_TIMEOUT       300
-
-REPDIR                 /var/anoncvs/cvsroot
-TMPDIR                 /var/anoncvs/tmp
-LISTFILE               /usr/local/etc/mmanoncvs.list
-MAX_RECURSION          20
-KEEP_EXEC              TRUE
-.Ed
-.El
-.Ss Using the public CVS pserver
-Although this does not consist of a CVS manual, because some of the aspects
-are configuration-dependant, it is a good idea to post on the HTTP site
-of a project how users can query the anonymous server.
-If the examples were followed, access would be as followed to checkout:
-.Pp
-.Bd -literal -offset indent
-$ cvs -d:pserver:anoncvs@<somesite>:/cvsroot login
-password: <empty>
-
-$ cvs -z6 -d:pserver:anoncvs@<somesite>:/cvsroot co <module>
-.Ed
-.Ss Troubleshooting
-If there are access problems such as
-.Nm anoncvs: no such user ,
-either that the username chosen during configuration was different than
-user 'anoncvs', which the
-.Nm CVSROOT/passwd
-and
-.Nm CVSROOT/readers
-files are set to use by
-.Xr mmanoncvs 8 .
-Another possibility is that the
-.Nm /etc/passwd
-or other equivalent files were not setup properly for your OS in the new root
-(typically
-.Nm /var/anoncvs/etc/passwd
-and friend(s)).
-.Pp
-If a complaint about
-.Nm /dev/null: no such file or directory
-arises, make sure to create the special character device file and to set it's
-permissions as described in the configuration section above.
-.Pp
-Although
-.Xr mmanoncvs 8
-attempts to make repository updates as atomic as possible, if a user complains
-that inconsistent CVS checkouts or updates happen occasionally, make sure that
-the
-.Nm ALOCK_*
-related parameters are set right in both
-.Xr mmspawnd.conf 5
-and
-.Xr mmanoncvs.conf 5
-configuration files to work with eachother. Also, there are two possible
-problems which can occur with concurrency and CVS-friendly locking, if not
-setup properly: The source repositories'
-.Nm CVSROOT/config
-file should not set an alternate LockDir option. If it does, it is possible
-for
-.Xr cvs 1
-and
-.Xr mmanoncvs 8
-to mistakenly rely on different locations for locking. Also, it is important
-for
-.Xr mmanoncvs 8
-to be able to create directories and files in the source
-repositories if consistancy is wanted with concurrency, because this is
-where it needs to create lock directories and files. This is how the CVS
-protocol works. Disabling
-.Nm CVS_LOCKING
-in
-.Xr mmanoncvs.conf 5
-or running
-.Xr mmanoncvs 8
-as an unprivileged user can often lead to problems in that
-area. The unprivileged user in that case should be part of a group set
-in
-.Nm GROUPS
-which is allowed write access to the source repositories.
-.Pp
-If you get other problems, it is possible that the cvs executable is linked
-dynamically, and that it cannot properly load it's required library files.
-Make sure to use the
-.Xr ldd 1
-command to detect which libraries should be copied to the library directory.
-Many operating systems also require a special executable to be present on the
-system for the dynamic loader to be invoked by other binaries. Using
-.Xr ktrace 1 ,
-.Xr strace 1
-command or equivalent would help detect which system calls failed during the
-cvs startup. To waste less time and avoid alot of problems, using a statically
-linked executable for cvs is a very good idea. No
-.Nm /lib
-directory is required then.
-.Pp
-When working with a dynamically linked setup, it may be good to temporary
-place a shell into the new root's
-.Nm /bin ,
-and to use the
-.Xr chroot 8
-command to test that the cvs executable indeed runs. It is recommended to
-delete that shell from the new root afterwards.
-.Pp
-If other permissions problem occur, verify that your configuration comforms
-to the instructions of this file. You can alternatively use the
-.Xr su 1
-command to test that the files are accessible under the anoncvs user. It is a
-good idea to have the 'anoncvs' user map to the same UID on both the actual
-system and the new root in their passwd files, which makes configuration
-easier.  A common issue not setting
-.Nm /cvsroot
-to have the unprivileged user as it's owner with write permissions, and
-.Nm /tmp
-to not have write access for 'anoncvs' group. Or, the unprivileged user is
-not part of the 'anoncvs' group. It is also possible that
-.Xr mmspawnd 8
-was not configured to set the
-.Nm ALOCK_USER
-parameter in
-.Xr mmspawnd.conf 5
-to the right unprivileged user.
-.Pp
-Make sure that the 'anoncvs' and 'anoncvsa' users cannot be used by other users
-using the
-.Xr su 1
-command. They should consist of disabled accounts. If your system does not
-allow passwordless disabled users, make sure to use the
-.Xr passwd 1
-command for each to specify a hard to guess password. It is important that the
-sensitive files in the new root's
-.Nm /etc
-do not allow the anoncvs user to read those password hashes then.
-.Pp
-If you get
-.Nm Cannot drop privileges
-errors from
-.Xr mmanoncvs 8 ,
-you either should set
-.Nm DROP_PRIVS
-to FALSE in
-.Xr mmanoncvs.conf 5
-and ensure that the unprivileged user which launches the program has the
-appropriate permissions for the mirror process to work. Another solution is
-to launch
-.Xr mmanoncvs 8
-as root, where it can optionally change it's permissions to the wanted
-.Nm USER
-and
-.Nm GROUPS
-if
-.Nm DROP_PRIVS
-is TRUE, or run as the superuser all along setting
-.Xr DROP_PRIVS
-to FALSE.
-.Pp
-If
-.Xr mmspawnd 8
-complains that your
-.Xr cvs 1
-executable is invalid, make sure that it has the mode described in the above
-configuration, and that it indeed consists of an ELF executable. This can
-be done by using the
-.Xr hexdump 1 ,
-.Xr od 1
-or
-.Xr xxd 1
-command to ensure that the ELF string is indeed located in the first four
-bytes of the file.
-.Xr mmspawnd 8
-does not currently allow to execute other types of binary files. If support
-for a.out is important for you, please send me a copy of your CVS executable
-so that I can make it support a.out, too.
-.Pp
-Note that
-.Xr mmanoncvs 8
-creates temporary directories in
-.Nm TMPDIR ,
-as well as CVS-friendly locks in the repositories. If broken in operation by
-a signal, it attempts to delete both locks and temporary directories. If you
-do notice that it often complains about already held CVS locks on repositories,
-and that
-.Nm #cvs.lock
-and
-.Nm #cvs.rfl.*
-files exist in each directory of the repository, owned by the user running
-.Xr mmanoncvs 8 ,
-it probably could not free those locks for some reason; This can happen as well
-for
-.Xr cvs 1 ,
-and is usually the result of a system crash during operation. If this occurs,
-you can use the following commands:
-.Bd -literal -offset indent
-# cd <repository>
-# find . -name '#cvs.lock' | xargs rmdir
-# find . -name '#cvs.rfl.*' | xargs rm
-# cd /var/anoncvs/tmp
-# ls -d mmanoncvs.* | xargs rm -rf
-.Ed
-.Pp
-When things do not work as intended, it may be a good idea to enable logging
-of stderr to a temporary file using the
-.Nm STDERR_FILE
-.Xr mmspawnd.conf
-parameter. Make sure to not use this feature on a production system however,
-as the file will grow indefinitely (and using a program to rotate the file
-will require to restart
-.Xr mmspawnd 8 ) .
-This also can be useful in conjunction with a program like
-.Xr ktrace 1
-or
-,Xr strace 1 ,
-which can be provided as the first part of the
-.Nm COMMAND
-parameter, provided that it is available in the new root, and is either
-statically linked, or has the required dynamic modules installed in the new
-root to function properly. You also will want to remove the tracing command
-before putting the system on production.
-.Sh FILES
-.Bl -tag -width indent -offset indent
-.It Pa /usr/local/sbin/mmanoncvs
-The binary of this program
-.It Pa /usr/local/etc/mmanoncvs.conf
-The default
-.Xr mmanoncvs.conf 5
-configuration file to read
-.It Pa /usr/local/etc/mmanoncvs.list
-The default
-.Xr mmanoncvs.list 5
-configuration file to read
-.El
-.Sh AUTHOR
-.Nm
-was written by Matthew Mondor, and is
-Copyright (c) 2003-2004, Matthew Mondor, All Rights Reserved.
-.Sh SEE ALSO
-.Xr mmanoncvs.conf 5 ,
-.Xr mmanoncvs.list 5 ,
-.Xr elf 5 ,
-.Xr mmspawnd 8 ,
-.Xr cvs 1 ,
-.Xr ldd 1 .
-.Sh BUGS
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/mmanoncvs/mmanoncvs.c b/mmsoftware/mmanoncvs/mmanoncvs.c
deleted file mode 100644 (file)
index 1d23017..0000000
+++ /dev/null
@@ -1,1425 +0,0 @@
-/* $Id: mmanoncvs.c,v 1.28 2004/10/05 15:39:04 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003-2004, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Program to setup and update a read-only mirror repository for anoncvs
- * pserver access using mmspawnd(8). Carefully read the mmanoncvs(8) manual
- * page, as well as mmanoncvs.conf(5) for details and setup instructions.
- * Was made in an attempt to be as secure as possible, even when running as
- * the superuser. In fact, most setups will require to run this as root
- * via a cron event scheduler, so that CVS read locks may be created in
- * the user CVS repositories. If you can read C, please take care to audit
- * this code and report any discovered security issue to mmondor@accela.net
- * so that we update the official distribution as fast as possible.
- * In a sense, this is paranoiaware :)
- */
-
-
-
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <string.h>    /* strerror(3) */
-#include <limits.h>    /* PATH_MAX */
-#include <signal.h>
-#include <errno.h>
-
-/* See mmlib/ directory for corresponding manual pages for more information */
-#include <mmtypes.h>
-#include <mmstring.h>
-#include <mmreadcfg.h>
-#include <mmlog.h>
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2003\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmanoncvs.c,v 1.28 2004/10/05 15:39:04 mmondor Exp $");
-
-
-
-/* DEFINITIONS */
-
-#define PROGRAM_NAME   "mmanoncvs"
-#define PROGRAM_VERSION        "0.0.2/mmondor"
-
-struct configuration {
-    char LOCK_PATH[256], USER[32], GROUPS[256], ALOCK_PATH[256], TMPDIR[256],
-       REPDIR[256], LISTFILE[256], REPGROUP[32];
-    long CVS_LOCK_DELAY, CVS_LOCK_TIMEOUT, MAX_RECURSION, MAX_FILESIZE;
-    bool DROP_PRIVS, CVS_LOCKING, ALOCK_LOCKING, KEEP_EXEC;
-};
-
-/* This is used to create the files in CVSROOT/. If contents is NULL, a
- * directory is created.
- */
-struct cvsroot_file {
-    mode_t mode;
-    const char *name;
-    const char *contents;
-};
-
-/* Used internally to store the contents of a directory after locks have been
- * checked for and sanity checking performed to reject invalid files. Lock
- * files will not be included.
- */
-struct dir_node {
-    pnode_t node;
-    size_t size, namelen;
-    int flags;
-    char name[PATH_MAX];
-};
-
-/* dir_node->flags */
-#define DNF_DIRECTORY  (1 << 0)
-#define DNF_EXECUTABLE (1 << 1)
-
-/* Because of the way CVS works, we must obtain a read access lock in the
- * whole repository, recursively, before we can proceed. Moreover, in a case
- * where we need to retry because if a lock which could not be obtained,
- * we must free all successful locks in the same order, and then try again
- * recursively on the whole tree, to prevent deadlocks. The following
- * represents a successfully locked directory in a tree. This way we can
- * easily revert and delete all obtained locks.
- */
-struct tree_node {
-    pnode_t node;
-    size_t namelen;
-    list_t dir;
-    char name[PATH_MAX];
-};
-
-/* Errors returned by tree_open() and dir_open() */
-enum errs {
-    E_OK = 0,
-    E_LOCKED,
-    E_NOMEM,
-    E_NOTFOUND,
-    E_PERM,
-    E_WRITE,
-    E_RLEVEL,
-    E_MAX
-};
-
-/* Useful macro to map enum errs codes to strings */
-#define STRERROR(e)    (errs_strs[(e)])
-
-/* The size of the file copy buffer in bytes */
-#define COPYBUF_SIZE   65536
-
-
-
-/* PROTOTYPES */
-
-int main(int, char **);
-static void main_mirror(void);
-
-static void sighandler(int);
-static int lock_check(const char *);
-
-static bool tmpdir_create(char *);
-static void tmpdir_delete(char *);
-static void tmpdir_save(char *);
-
-static bool cvsroot_build(const char *);
-static bool cvsroot_delete(const char *);
-
-static bool dir_valid(char *);
-static bool dir_make(const char *, const char *);
-static int dir_open(list_t *, const char *, bool);
-static void dir_close(list_t *);
-static int tree_open(list_t *, const char *, bool);
-static int tree_open_r(list_t *, const char *, bool);
-static void tree_close(list_t *, bool);
-static bool tree_copy(const char *, const char *);
-static bool file_copy(struct dir_node *, const char *, size_t);
-static bool tree_delete(const char *);
-
-static bool mm_chgrp(const char *);
-
-
-
-/* GLOBALS */
-
-/* Map of E_* errors to strings */
-static const char *errs_strs[E_MAX] = {
-    "Success",
-    "Lock exists",
-    "Out of memory",
-    "No such file or directory",
-    "Permission denied",
-    "Write I/O error",
-    "Maximum recursion level exceeded"
-};
-
-/* Contents of CVSROOT directory */
-static const struct cvsroot_file cvsroot_files[] = {
-    {0755, "Emptydir", NULL},
-    {0644, "checkoutlist", ""},
-    {0644, "commitinfo", ""},
-    {0644, "config", "SystemAuth=no\nLockDir=/tmp\nLogHistory=\n"},
-    {0644, "cvswrappers", ""},
-    {0644, "editinfo", ""},
-    {0644, "history", ""},
-    {0644, "loginfo", ""},
-    {0644, "modules", ""},
-    {0644, "notify", ""},
-    {0644, "passwd", "anoncvs::anoncvs\n"},
-    {0644, "rcsinfo", ""},
-    {0644, "readers", "anoncvs\n"},
-    {0644, "taginfo", ""},
-    {0664, "val-tags", ""},
-    {0644, "verifymsg", ""},
-    {0000, NULL, NULL}
-};
-
-/* Various required globals */
-static struct configuration CONF;
-static FILE *fh_reps = NULL;
-static int runlock = -1;
-static pool_t dir_pool, tree_pool;
-static pid_t pid;
-static long recursion_level = 0;
-static off_t ssize_max;
-static gid_t repgroup;
-/* Used by main_mirror(), tree_copy(), tmpdir_save() and sighandler() */
-static list_t gtree;
-static char gtmpdir[PATH_MAX], gtmpdir2[PATH_MAX];
-static char *copybuf;
-
-
-
-/* CODE */
-
-int main(int argc, char **argv)
-{
-    char *conf_file = "/usr/local/etc/mmanoncvs.conf";
-    pid_t uid;
-    gid_t *gids;
-    int ngids, c;
-    cres_t cres;
-    carg_t *cargp;
-    carg_t cargs[] = {
-       {CAT_STR, CAF_NONE, 1, 255, "LOCK_PATH", CONF.LOCK_PATH},
-       {CAT_STR, CAF_NONE, 1, 31, "USER", CONF.USER},
-       {CAT_STR, CAF_NONE, 1, 255, "GROUPS", CONF.GROUPS},
-       {CAT_STR, CAF_NONE, 1, 255, "ALOCK_PATH", CONF.ALOCK_PATH},
-       {CAT_STR, CAF_NONE, 1, 255, "TMPDIR", CONF.TMPDIR},
-       {CAT_STR, CAF_NONE, 1, 255, "REPDIR", CONF.REPDIR},
-       {CAT_STR, CAF_NONE, 1, 255, "LISTFILE", CONF.LISTFILE},
-       {CAT_STR, CAF_NONE, 1, 31, "REPGROUP", CONF.REPGROUP},
-       {CAT_VAL, CAF_NONE, 1, 600, "CVS_LOCK_DELAY", &CONF.CVS_LOCK_DELAY},
-       {CAT_VAL, CAF_NONE, 1, 99999, "CVS_LOCK_TIMEOUT",
-           &CONF.CVS_LOCK_TIMEOUT},
-       {CAT_VAL, CAF_NONE, 1, 99, "MAX_RECURSION", &CONF.MAX_RECURSION},
-       {CAT_VAL, CAF_NONE, 1, 2147483647, "MAX_FILESIZE", &CONF.MAX_FILESIZE},
-       {CAT_BOOL, CAF_NONE, 0, 0, "DROP_PRIVS", &CONF.DROP_PRIVS},
-       {CAT_BOOL, CAF_NONE, 0, 0, "CVS_LOCKING", &CONF.CVS_LOCKING},
-       {CAT_BOOL, CAF_NONE, 0, 0, "ALOCK_LOCKING", &CONF.ALOCK_LOCKING},
-       {CAT_BOOL, CAF_NONE, 0, 0, "KEEP_EXEC", &CONF.KEEP_EXEC},
-       {CAT_END, CAF_NONE, 0, 0, NULL, NULL}
-    };
-
-    /* Parse command line arguments */
-    while ((c = getopt(argc, argv, "f:")) != -1) {
-       switch (c) {
-       case 'f':
-           conf_file = optarg;
-           break;
-       case '?':
-           /* FALLTHROUGH */
-       default:
-           (void) fprintf(stderr, "usage: mmanoncvs [-f <configfile>]\n");
-           exit(EXIT_FAILURE);
-       }
-    }
-    argc -= optind;
-    argv += optind;
-
-    /* We only need stderr for logging/errors. */
-    (void) setvbuf(stdin, NULL, _IOFBF, 0);
-    (void) setvbuf(stdout, NULL, _IOFBF, 0);
-    (void) setvbuf(stderr, NULL, _IOFBF, 0);
-    (void) freopen("/dev/null", "r", stdin);
-    (void) freopen("/dev/null", "w", stdout);
-
-    /* Set configuration defaults */
-    (void) mm_strcpy(CONF.LOCK_PATH, "/tmp/mmanoncvs.lock");
-    (void) mm_strcpy(CONF.USER, "anoncvsa");
-    (void) mm_strcpy(CONF.GROUPS, "anoncvs,users");
-    (void) mm_strcpy(CONF.ALOCK_PATH,
-                    "/var/run/mmspawnd-anoncvs.alock");
-    (void) mm_strcpy(CONF.TMPDIR, "/var/anoncvs/tmp");
-    (void) mm_strcpy(CONF.REPDIR, "/var/anoncvs/cvsroot");
-    (void) mm_strcpy(CONF.LISTFILE, "/usr/local/etc/mmanoncvs.list");
-    (void) mm_strcpy(CONF.REPGROUP, "anoncvs");
-    CONF.CVS_LOCK_DELAY = 30;
-    CONF.CVS_LOCK_TIMEOUT = 300;
-    CONF.MAX_RECURSION = 20;
-    CONF.MAX_FILESIZE = 2147483647;
-    CONF.DROP_PRIVS = FALSE;
-    CONF.CVS_LOCKING = TRUE;
-    CONF.ALOCK_LOCKING = TRUE;
-    CONF.KEEP_EXEC = TRUE;
-
-    /* Read config file */
-    if (!mmreadcfg(&cres, cargs, conf_file)) {
-       /* Error parsing configuration file, report which */
-       (void) fprintf(stderr, "\nError parsing '%s'\n", conf_file);
-       (void) fprintf(stderr, "Error  : %s\n", mmreadcfg_strerr(cres.CR_Err));
-       if (*(cres.CR_Data))
-           (void) fprintf(stderr, "Data   : %s\n", cres.CR_Data);
-       if ((cargp = cres.CR_Keyword) != NULL) {
-           (void) fprintf(stderr, "Keyword: %s\n", cargp->CA_Keyword);
-           (void) fprintf(stderr, "Minimum: %ld\n", cargp->CA_Min);
-           (void) fprintf(stderr, "Maximum: %ld\n", cargp->CA_Max);
-       }
-       if (cres.CR_Line != -1)
-           (void) fprintf(stderr, "Line   : %d\n", cres.CR_Line);
-       (void) fprintf(stderr, "\n");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Post parsing */
-    if (CONF.DROP_PRIVS) {
-       if ((uid = mmgetuid(CONF.USER)) == -1) {
-           (void) fprintf(stderr, "\nUnknown USER '%s'\n\n", CONF.USER);
-           exit(EXIT_FAILURE);
-       }
-       if (!(gids = mmgetgidarray(&ngids, CONF.GROUPS))) {
-           (void) fprintf(stderr,
-                          "\nOne of following GROUPS unknown: '%s'\n\n",
-                          CONF.GROUPS);
-           exit(EXIT_FAILURE);
-       }
-    } else {
-       uid = 0;
-       gids = NULL;
-    }
-    if ((repgroup = mmgetgid(CONF.REPGROUP)) == -1) {
-       (void) fprintf(stderr, "\nREPGROUP '%s' unknown\n\n", CONF.REPGROUP);
-       exit(EXIT_FAILURE);
-    }
-    if (!dir_valid(CONF.REPDIR)) {
-       (void) fprintf(stderr, "\nREPDIR '%s' should begin with '/'\n\n",
-                      CONF.REPDIR);
-       exit(EXIT_FAILURE);
-    }
-    if (!dir_valid(CONF.TMPDIR)) {
-       (void) fprintf(stderr, "\nTMPDIR '%s' should begin with '/'\n\n",
-                      CONF.TMPDIR);
-       exit(EXIT_FAILURE);
-    }
-    if ((fh_reps = fopen(CONF.LISTFILE, "r")) == NULL) {
-       (void) fprintf(stderr, "\nCannot open LISTFILE '%s' - (%s)\n\n",
-                      CONF.LISTFILE, strerror(errno));
-       exit(EXIT_FAILURE);
-    }
-
-    /* Initialization */
-
-    /* The modes for open(2) and mkdir(2) are relative to the umask(2) for
-     * the process
-     */
-    (void) umask(0);
-    if (!pool_init(&dir_pool, "dir_pool", malloc, free, NULL, NULL,
-               sizeof(struct dir_node), 65536 / sizeof(struct dir_node),
-               1, 0) ||
-           !pool_init(&tree_pool, "tree_pool", malloc, free, NULL, NULL,
-               sizeof(struct tree_node), 65536 / sizeof(struct tree_node),
-               1, 0) ||
-           (copybuf = malloc(COPYBUF_SIZE)) == NULL) {
-       (void) fprintf(stderr, "\nOut of memory\n\n");
-       exit(EXIT_FAILURE);
-    }
-
-    /* A few constants for the duration of the program which we record now */
-    pid = getpid();
-    ssize_max = (off_t)CONF.MAX_FILESIZE;
-
-    /* Make sure that only one instance is running to prevent self-recursion
-     * issues. If it takes a considerable time to perform our tasks because
-     * of CVS locks on a repository, this would prevent undefined behavior.
-     * We need to do this before we drop privileges.
-     */
-    if ((runlock = lock_check(CONF.LOCK_PATH)) == -1) {
-       (void) fprintf(stderr, "\n%s already running\n\n", PROGRAM_NAME);
-       exit(EXIT_FAILURE);
-    }
-
-    /* Finally drop privileges if requested. Although this is a nice feature,
-     * We need to both be able to access the mmspawnd ALOCK for the CVS
-     * pserver, as well as to have permissions to create files and directories
-     * in the source repositories to be mirrorred (this is required for proper
-     * cooperation with CVS under concurrency).
-     */
-    if (CONF.DROP_PRIVS) {
-       if (!mmdropprivs(uid, gids, ngids)) {
-           (void) fprintf(stderr, "\nCould not drop privileges!\n\n");
-           exit(EXIT_FAILURE);
-       }
-    }
-
-    /* Verify if we can access the mmspawnd ALOCK, with our new permissions.
-     * If we just obtained a filedescriptor to it now with open(2) we would
-     * need to assume that it never be restarted during our runtime, which
-     * we want to avoid doing.
-     */
-    if (CONF.ALOCK_LOCKING && (access(CONF.ALOCK_PATH, R_OK)) == -1) {
-       (void) fprintf(stderr, "Cannot access '%s' mmspawnd lock file\n\n",
-                      CONF.ALOCK_PATH);
-       exit(EXIT_FAILURE);
-    }
-
-    /* Setup our signal handler which will call tree_close(&gtree, TRUE) if
-     * CONF.CVS_LOCKING is TRUE
-     */
-    {
-       struct sigaction act;
-
-       DLIST_INIT(&gtree);
-       *gtmpdir = *gtmpdir2 = '\0';
-       act.sa_handler = sighandler;
-       act.sa_flags = 0;
-       (void) sigemptyset(&act.sa_mask);
-       (void) sigaction(SIGTERM, &act, NULL);
-       (void) sigaction(SIGINT, &act, NULL);
-       (void) sigaction(SIGSEGV, &act, NULL);
-    }
-
-    /* Finally perform our work */
-    main_mirror();
-    /* NOTREACHED */
-
-    exit(EXIT_SUCCESS);
-}
-
-
-/* This is the glue of the system. */
-static void main_mirror(void)
-{
-    char line[1024], buf[PATH_MAX], *cols[3];
-    int lines;
-    bool ok = TRUE;
-
-    if (!tmpdir_create(gtmpdir))
-       exit(EXIT_FAILURE);
-    if (!cvsroot_build(gtmpdir)) {
-       tmpdir_delete(gtmpdir);
-       exit(EXIT_FAILURE);
-    }
-
-    for (lines = 1; fgets(line, 1023, fh_reps) != NULL; lines++) {
-       char *cptr;
-
-       /* Make sure to ignore comments and empty lines */
-       for (cptr = line; *cptr == ' ' || *cptr == '\t'; cptr++) ;
-       if (*cptr == '\r' || *cptr == '\n' || *cptr == '#' || *cptr == ';')
-           continue;
-
-       /* Now isolate the two columns, stripping ending '\n' or '\r\n' too */
-       if (mm_strasplq(cols, line, 2) != 2) {
-           (void) fprintf(stderr, "Invalid line %d in '%s'\n", lines,
-                          CONF.LISTFILE);
-           continue;
-       }
-
-       /* Make sure that each path begins with a '/', and strip any trailing
-        * ones.
-        */
-       if (!dir_valid(cols[0])) {
-           (void) fprintf(stderr,
-                          "Invalid destination path '%s' at line %d in %s\n",
-                          cols[0], lines, CONF.LISTFILE);
-           continue;
-       }
-       if (!dir_valid(cols[1])) {
-           (void) fprintf(stderr,
-                          "Invalid source path '%s' at line %d in %s\n",
-                          cols[1], lines, CONF.LISTFILE);
-           continue;
-       }
-
-       /* Both pathnames seem valid; We now need to create the directories
-        * for the destination as required in <tmpdir>. We then can attempt
-        * the copy. If it fails, we abandon to leave the last successful
-        * backup.
-        */
-       (void) snprintf(buf, PATH_MAX - 1, "%s%s", gtmpdir, cols[0]);
-       if (!dir_make(gtmpdir, cols[0]) || !tree_copy(buf, cols[1])) {
-           (void) fprintf(stderr, "Errors to mirror '%s' to '%s%s' "
-                          "(line %d). Aborting mirror to keep previous "
-                          "successful backup.\n",
-                          cols[1], CONF.REPDIR, cols[0], lines);
-           ok = FALSE;
-           break;
-       }
-    }
-    (void) fclose(fh_reps);
-
-    if (ok) {
-       /* Everything successful; Replace old repository by new one */
-       tmpdir_save(gtmpdir);
-       exit(EXIT_SUCCESS);
-    } else {
-       /* Delete temporary directory */
-       tmpdir_delete(gtmpdir);
-       exit(EXIT_FAILURE);
-    }
-}
-
-
-/* This signal handler attempts to unlink all acquired locks as well as\
- * temporary work directories.
- */
-static void sighandler(int sig)
-{
-    sigset_t set;
-
-    /* A signal handler may be broken by another signal. Because we perform
-     * the same operation for all three signals we handle, and that we only
-     * want to perform it once, block signals we expect to receive.
-     */
-    (void) sigemptyset(&set);
-    (void) sigaddset(&set, SIGTERM);
-    (void) sigaddset(&set, SIGINT);
-    (void) sigaddset(&set, SIGSEGV);
-    (void) sigprocmask(SIG_BLOCK, &set, NULL);
-
-    switch (sig) {
-    case SIGTERM:
-       /* FALLTHROUGH */
-    case SIGINT:
-       /* FALLTHROUGH */
-    case SIGSEGV:
-       /* FALLTHROUGH */
-    default:
-       (void) fprintf(stderr, "Received signal %d, attempting to cleanup\n",
-                      sig);
-       tree_close(&gtree, CONF.CVS_LOCKING);
-       tmpdir_delete(gtmpdir);
-       tmpdir_delete(gtmpdir2);
-       exit(EXIT_FAILURE);
-    }
-}
-
-
-/* Used to prevent self-recursion. Returns -1 if the lock is already held, or
- * the filedescriptor to the lock file (which we should not close until we
- * exit).
- */
-static int lock_check(const char *file)
-{
-    int fd;
-
-    if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600)) != -1) {
-       if ((flock(fd, LOCK_EX | LOCK_NB)) == 0)
-           return fd;
-       (void) close(fd);
-    } else
-       (void) fprintf(stderr, "lock_check() - open(%s) - (%s)\n", file,
-                      strerror(errno));
-
-    return -1;
-}
-
-
-/* Attempts to create a unique directory in CONF.TMPDIR, in which it will
- * mirror the repositories, until we either delete it on failure, or move it
- * over the old official CVS pserver repository REPDIR on success. Obtains an
- * unsigned long worth of "/dev/urandom" device, and uses 4.2BSD srandom(3)/
- * random(3) which are better than ANSI rand(3)/srand(3), and available on
- * most unices. On success, returns TRUE and sets <tmpdir> to the absolute
- * fullpath to the new directory.
- */
-static bool tmpdir_create(char *tmpdir)
-{
-    int fd;
-    bool ok = FALSE;
-    unsigned long seed;
-    char buf[PATH_MAX];
-    int i;
-
-    *tmpdir = '\0';
-    if ((fd = open("/dev/urandom", O_RDONLY)) != -1) {
-       if (read(fd, &seed, sizeof(unsigned long)) == sizeof(unsigned long)) {
-           srandom(seed);
-           /* We stop after 64 failed mkdir(2) attempts with EEXIST */
-           for (i = 0; i < 64; i++) {
-               (void) snprintf(buf, PATH_MAX - 1, "%s/%s.%ld",
-                               CONF.TMPDIR, PROGRAM_NAME, random());
-               if (mkdir(buf, 0755) == 0) {
-                   if (mm_chgrp(buf)) {
-                       ok = TRUE;
-                       (void) mm_strncpy(tmpdir, buf, PATH_MAX - 1);
-                   } else
-                       (void) rmdir(buf);
-                   break;
-               } else if (errno != EEXIST) {
-                   (void) fprintf(stderr,
-                                  "tmpdir_create() - mkdir(%s) - (%s)\n",
-                                  buf, strerror(errno));
-                   break;
-               }
-           }
-           if (i == 64)
-               (void) fprintf(stderr,
-                              "tmpdir_create() - Failed after 64 attempts\n");
-       }
-       (void) close(fd);
-    }
-
-    return ok;
-}
-
-
-/* Deletes everything we may have created in <tmpdir>, as well as <tmpdir>
- * itself.
- */
-static void tmpdir_delete(char *tmpdir)
-{
-    if (*tmpdir != '\0') {
-       (void) cvsroot_delete(tmpdir);
-       (void) tree_delete(tmpdir);
-       (void) rmdir(tmpdir);
-       *tmpdir = '\0';
-    }
-}
-
-
-/* Attempts to atomically use rename(2) to move the tmpdir to REPDIR.
- * This is supposed to either repace the current REPDIR instantly, or
- * to create it if it does not exist. We ensure to hold the mmspawnd(8)
- * ALOCK synchronization lock for a very short moment during the move.
- * This will wait until no more pserver processes are running, and will
- * prevent any from being started while we hold the lock. This mmspawnd(8)
- * feature, along with mmanoncvs(8)'s CVS friendly locking support, ensure
- * clean operation with concurrency. We wouldn't want users to complain about
- * partial or conflicting CVS updates.
- */
-static void tmpdir_save(char *tmpdir)
-{
-    int fd = -1;
-    bool ok = FALSE;
-    bool locked;
-
-    if (tmpdir_create(gtmpdir2)) {
-       if (CONF.ALOCK_LOCKING) {
-           locked = FALSE;
-           if ((fd = open(CONF.ALOCK_PATH, O_RDONLY)) != -1) {
-               if ((flock(fd, LOCK_EX)) == 0)
-                   locked = TRUE;
-               else
-                   (void) fprintf(stderr,
-                                  "tmpdir_save() - flock(%s) - (%s)\n",
-                                  CONF.ALOCK_PATH, strerror(errno));
-           } else
-               (void) fprintf(stderr, "tmpdir_save() - open(%s) - (%s)\n",
-                              CONF.ALOCK_PATH, strerror(errno));
-       } else
-           locked = TRUE;
-       if (locked) {
-           if (rename(CONF.REPDIR, gtmpdir2) == 0) {
-               if (rename(tmpdir, CONF.REPDIR) == 0)
-                   ok = TRUE;
-               else
-                   (void) fprintf(stderr,
-                                  "tmpdir_save() - rename(%s,%s) - (%s)\n",
-                                  tmpdir, CONF.REPDIR, strerror(errno));
-           } else
-               (void) fprintf(stderr,
-                              "tmpdir_save() - rename(%s,%s) - (%s)\n",
-                              CONF.REPDIR, gtmpdir2, strerror(errno));
-           if (CONF.ALOCK_LOCKING)
-               (void) flock(fd, LOCK_UN);
-       }
-       if (fd != -1)
-           (void) close(fd);
-       tmpdir_delete(gtmpdir2);
-    }
-
-    if (!ok) {
-       (void) fprintf(stderr, "Deleting temporary directory '%s' since we "
-                      "could not update '%s' with it. This cancels the "
-                      "update, the previous anoncvs repository remains "
-                      "unchanged.\n",
-                      tmpdir, CONF.REPDIR);
-       tmpdir_delete(tmpdir);
-    }
-}
-
-
-/* There are no user-supplied pathnames here, we can just use snprintf(3)
- * safely. <rootpath> is provided by the program, previously generated and
- * set to a directory name in the temporary directory. This function creates
- * the anonymous CVS repository's CVSROOT directory with it's contents. The
- * setup it creates is to work with the mmspawnd(8) daemon with a chroot(2)
- * based configuration. The LockDir option in the CVSROOT/config file is
- * set to "/tmp", so that repository access may be read-only for the anoncvs
- * user.
- */
-static bool cvsroot_build(const char *rootpath)
-{
-    const struct cvsroot_file *f;
-    bool ok = TRUE;
-    char buf[PATH_MAX];
-
-    /* First attempt to create the CVSROOT directory */
-    (void) snprintf(buf, PATH_MAX - 1, "%s/CVSROOT", rootpath);
-    if (mkdir(buf, 0755) == -1) {
-       (void) fprintf(stderr, "cvsroot_build() - mkdir(%s) - (%s)\n", buf,
-                      strerror(errno));
-       return FALSE;
-    }
-    if (!mm_chgrp(buf))
-       return FALSE;
-
-    /* Then build the CVSROOT/ file structure */
-    for (f = cvsroot_files; f->name != NULL; f++) {
-       (void) snprintf(buf, PATH_MAX - 1, "%s/CVSROOT/%s", rootpath, f->name);
-       if (f->contents == NULL) {
-           /* Directory creation attempt */
-           if (mkdir(buf, f->mode) == -1) {
-               (void) fprintf(stderr, "cvsroot_build() - mkdir(%s) - (%s)\n",
-                              buf, strerror(errno));
-               ok = FALSE;
-           }
-           if (!mm_chgrp(buf))
-               ok = FALSE;
-       } else {
-           int fd;
-           size_t len;
-
-           /* File creation attempt */
-           if ((fd = open(buf, O_CREAT | O_WRONLY, f->mode)) != -1) {
-               len = mm_strlen(f->contents);
-               if (len != 0) {
-                   if (write(fd, f->contents, len) != len) {
-                       (void) fprintf(stderr,
-                                      "cvsroot_build() - write(%s) - (%s)\n",
-                                      buf, strerror(errno));
-                       ok = FALSE;
-                   }
-               }
-               if (close(fd) == -1) {
-                   (void) fprintf(stderr,
-                                  "cvsroot_build() - close(%s) - (%s)\n",
-                                  buf, strerror(errno));
-                   ok = FALSE;
-               }
-               if (!mm_chgrp(buf))
-                   ok = FALSE;
-           } else {
-               (void) fprintf(stderr, "cvsroot_build() - open(%s) - (%s)\n",
-                              buf, strerror(errno));
-               ok = FALSE;
-           }
-       }
-    }
-
-    return ok;
-}
-
-
-/* This deletes the CVSROOT directory previously created using cvsroot_build().
- * This is required to delete the temporary data if a mirror operation fails,
- * as the tree_delete() function will ignore CVSROOT, and will consider the
- * files in it as invalid RCS files.
- */
-static bool cvsroot_delete(const char *rootpath)
-{
-    const struct cvsroot_file *f;
-    bool ok = TRUE;
-    char buf[PATH_MAX];
-
-    /* First delete the CVSROOT/ file structure */
-    for (f = cvsroot_files; f->name != NULL; f++) {
-       (void) snprintf(buf, PATH_MAX - 1, "%s/CVSROOT/%s", rootpath, f->name);
-       if (f->contents == NULL) {
-           /* Directory */
-           if (rmdir(buf) != 0) {
-               /*
-               (void) fprintf(stderr,
-                              "cvsroot_delete() - rmdir(%s) - (%s)\n",
-                              buf, strerror(errno));
-                */
-               ok = FALSE;
-           }
-       } else {
-           /* File */
-           if (unlink(buf) != 0) {
-               /*
-               (void) fprintf(stderr,
-                              "cvsroot_delete() - unlink(%s) - (%s)\n",
-                              buf, strerror(errno));
-                */
-               ok = FALSE;
-           }
-       }
-    }
-
-    /* Then attempt to delete the CVSROOT directory */
-    (void) snprintf(buf, PATH_MAX - 1, "%s/CVSROOT", rootpath);
-    if (rmdir(buf) != 0) {
-       /*
-       (void) fprintf(stderr, "cvsroot_delete() - rmdir(%s) - (%s)\n",
-                      buf, strerror(errno));
-        */
-       ok = FALSE;
-    }
-
-    return ok;
-}
-
-
-/* Returns TRUE if the supplied directory begins with a '/', and strips the
- * tailing '/' (if any). Returns FALSE otherwise.
- */
-static bool dir_valid(char *dirpath)
-{
-    if (*dirpath == '/') {
-       size_t len;
-
-       len = mm_strlen(dirpath) - 1;
-       while (len > 0 && dirpath[len] == '/') {
-           dirpath[len] = '\0';
-           len--;
-       }
-
-       return TRUE;
-    }
-
-    return FALSE;
-}
-
-
-/* Attempts to create the directories, if necessary, so that writing files
- * to /<rootpath>/<dirpath>/ be possible. Returns TRUE on success, or FALSE
- * on failure. Of course, we ignore EEXIST mkdir(2) errors. It assumes
- * <rootpath> to consist of an existing directory.
- * Both path elements must previously have been validated using dir_valid().
- */
-static bool dir_make(const char *rootpath, const char *dirpath)
-{
-    char buf[PATH_MAX], *cptr, *sptr;
-    size_t len;
-
-    (void) snprintf(buf, PATH_MAX - 1, "%s%s/", rootpath, dirpath);
-    sptr = &buf[mm_strlen(rootpath) + 1];
-    for (cptr = sptr; *cptr != '\0'; cptr++) {
-       if (*cptr == '/') {
-           if ((len = (cptr - sptr)) > 1) {
-               *cptr = '\0';
-               if (mkdir(buf, 0755) != 0 && errno != EEXIST) {
-                   (void) fprintf(stderr, "dir_make() - mkdir(%s) - (%s)\n",
-                                  buf, strerror(errno));
-                   return FALSE;
-               } else if (!mm_chgrp(buf))
-                   return FALSE;
-               *cptr = '/';
-               sptr = cptr + 1;
-           }
-       }
-    }
-
-    return TRUE;
-}
-
-
-/* This function consists of an opendir(3) replacement, which locks the
- * directory in a CVS friendly manner, eliminates invalid files, and stores
- * the fullpath of every file, along with their sizes. Requires the dir_pool
- * pool_t to previously be initialized. On fatal errors, such as out of memory,
- * permission denied, invalid directory, the lock is released and the
- * corresponding error code is returned (as defined by enum errs). Returns
- * E_OK on success, in which case the lock is held in place.
- * Note: This function is intended to be called by tree_open(), since
- * tree_close() is the only way to release the obtained locks if we returned
- * with E_OK. The supplied <dir> list_t should have been initialized using
- * DLIST_INIT().
- * Note that we do not support alternate LockDir option in CVSROOT/config,
- * we assume that the repositories do not specify an alternate value.
- * Otherwise we would be limited to copying complete repositories (we could
- * not handle normal directories which may be part of a repository). Moreover,
- * we would permit the maintainer of the repository to cause us to write
- * anywhere. They are thus advised to not specify an alternate LockDir unless
- * they are to expect occasionnal inconsistancies in the mirror (if they are
- * commiting changes at the same time the copying process occurs).
- */
-static int dir_open(list_t *dir, const char *dirpath, bool locking)
-{
-    DIR *dptr;
-
-    /* Only <dirpath> is allowed to be a symbolic link, for convenience. */
-    if ((dptr = opendir(dirpath)) != NULL) {
-       struct dirent *eptr;
-       struct dir_node *dnode;
-       char buf[PATH_MAX];
-
-       if (locking) {
-           int fd, error;
-
-           /* Attempt to obtain a CVS read lock. Note that mkdir(2) is
-            * atomic and that this is the official CVS way.
-            */
-           (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.lock", dirpath);
-           if (mkdir(buf, 0755) == -1) {
-               /* Failed to obtain the master lock */
-               switch (errno) {
-               case EEXIST:
-                   error = E_LOCKED;
-                   break;
-               case EACCES:
-                   /* FALLTHROUGH */
-               case EROFS:
-                   error = E_PERM;
-                   break;
-               default:
-                   error = E_WRITE;
-                   break;
-               }
-               (void) closedir(dptr);
-               dir_close(dir);
-               return error;
-           }
-           (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.rfl.%d", dirpath,
-                           (int)pid);
-           if ((fd = open(buf, O_CREAT | O_TRUNC | O_WRONLY, 0644)) == -1) {
-               /* Failed to write the CVS read lock, release master lock */
-               (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.locl", dirpath);
-               (void) rmdir(buf);
-               (void) closedir(dptr);
-               dir_close(dir);
-               return E_PERM;
-           }
-           (void) close(fd);
-       }
-
-       /* We could obtain our CVS read lock, keep it and proceed. */
-       while ((eptr = readdir(dptr)) != NULL) {
-           struct stat st;
-           int flags;
-
-           flags = 0;
-           /* Perform sanity checking on file, and make sure to verify for
-            * active write access locks, if any.
-            */
-           if (*eptr->d_name == '.' ||
-                   mm_strncmp(eptr->d_name, "CVS", 3) == 0)
-               continue;
-           (void) snprintf(buf, PATH_MAX - 1, "%s/%s", dirpath, eptr->d_name);
-           if (lstat(buf, &st) == -1) {
-               /* Release everything cleanly */
-               (void) fprintf(stderr, "dir_open(%s) - lstat(%s) - (%s)",
-                              dirpath, buf, strerror(errno));
-               (void) closedir(dptr);
-               dir_close(dir);
-               if (locking) {
-                   (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.rfl.%d",
-                                   dirpath, (int)pid);
-                   (void) unlink(buf);
-                   (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.lock", dirpath);
-                   (void) rmdir(buf);
-               }
-               return E_NOTFOUND;
-           }
-           if (S_ISREG(st.st_mode)) {
-               size_t len;
-               const char *path;
-
-               /* Officially a regular file, eliminate invalid ones. */
-               if (*eptr->d_name == '#')
-                   continue;
-               if (st.st_size > ssize_max) {
-                   (void) fprintf(stderr, "dir_open() - Ignoring '%s' "
-                                  "(abnormally large file)\n",
-                                  buf);
-                   continue;
-               }
-               path = eptr->d_name;
-               len = mm_strlen(path);
-               if (len < 3 ||
-                       (path[len - 1] != 'v' && path[len - 2] != ',')) {
-                   (void) fprintf(stderr, "dir_open() - Ignoring '%s' "
-                                  "(not a valid RCS filename)\n",
-                                  buf);
-                   continue;
-               }
-               if (CONF.KEEP_EXEC) {
-                   /* If we are allowed to set the executable bit on backups,
-                    * we have to set the DNF_EXECUTABLE flag bit
-                    */
-                   if ((st.st_mode & ~S_IFMT) & (S_IXUSR | S_IXGRP | S_IXOTH))
-                       flags |= DNF_EXECUTABLE;
-               }
-           } else if (S_ISDIR(st.st_mode)) {
-               /* Definitely a directory. Make sure that it has a valid
-                * name, or eliminate it.
-                */
-               if (*eptr->d_name == '#')
-                   continue;
-               flags |= DNF_DIRECTORY;
-           } else {
-               /* A special file or symbolic link. Ignore, and log.
-                * It could be a nice feature to use a hashtable_t with
-                * mmhash(3) instead of an mmlist(3) list_t and record the
-                * file/directory inodes, then verifying if any duplicate
-                * exists, revealing hard links (which can be the cause of
-                * recursive loops). However, we provide a recursive level
-                * limit, which is just as good, and it makes this section
-                * faster. Moreover, because of CVS-style locking, it would
-                * be impossible to acquire the lock twice on the same
-                * directory.
-                */
-               (void) fprintf(stderr, "dir_open() - Ignoring '%s' (not "
-                              "a regular file or directory)\n",
-                              buf);
-               continue;
-           }
-           /* Passed sanity checking; add entry in list */
-           if ((dnode = (struct dir_node *)pool_alloc(&dir_pool, FALSE))
-                   == NULL) {
-               /* Release everything cleanly */
-               (void) fprintf(stderr, "dir_open() - Out of memory\n");
-               (void) closedir(dptr);
-               dir_close(dir);
-               if (locking) {
-                   (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.rfl.%d",
-                                   dirpath, (int)pid);
-                   (void) unlink(buf);
-                   (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.lock",
-                                   dirpath);
-                   (void) rmdir(buf);
-               }
-               return E_NOMEM;
-           }
-           /* Trunkating to a size_t is safe as we eliminated too large
-            * files already the value may in fact fit safely into an ssize_t.
-            */
-           dnode->size = (size_t)st.st_size;
-           dnode->flags = flags;
-           dnode->namelen = mm_strncpy(dnode->name, buf, PATH_MAX - 1);
-           DLIST_APPEND(dir, (node_t *)dnode);
-       }
-       (void) closedir(dptr);
-    } else
-       return (errno == EACCES ? E_PERM : E_NOTFOUND);
-
-    return E_OK;
-}
-
-
-/* Frees all directory entries which dir_open() possibly recorded in the
- * specified list_t. Requires the dir_pool pool_t to previously have been
- * initialized. Safe to use on empty lists, as long as they at least have
- * previously been initialized once using DLIST_INIT().
- */
-static void dir_close(list_t *dir)
-{
-    struct dir_node *dnode, *tmp;
-
-    /* We don't just use DLIST_FOREACH() since we also are freeing nodes.
-     * If we didn't, we simply would need to DLIST_INIT(), actually. However,
-     * we want allocating and freeing of directory file contents to be
-     * reentrant so that it may safely be used recursively, while shareing
-     * the same global dir_pool pool_t for efficient memory management and
-     * minimizing calls to malloc(3)/free(3).
-     */
-    for (dnode = DLIST_TOP(dir); dnode != NULL; dnode = tmp) {
-       tmp = DLIST_NEXT(dnode);
-       (void) pool_free((pnode_t *)dnode);
-    }
-    DLIST_INIT(dir);
-}
-
-
-/* Wrapper for tree_open_r() */
-static int tree_open(list_t *tree, const char *dirpath, bool locking)
-{
-    recursion_level = 0;
-    DLIST_INIT(tree);
-    return tree_open_r(tree, dirpath, locking);
-}
-
-
-/* Attempts to recursively lock, in a CVS friendly way, every directory within
- * the specified <dirpath>, and obtain the file list of all the tree. If this
- * fails, tree_close() is automatically called. On error, one of (E_LOCKED,
- * E_NOMEM, E_NOTFOUND, E_PERM, E_RLEVEL) is returned (and everything freed).
- * Returns E_OK on success, in which case all directories are locked, and
- * where tree_copy() may be used before calling tree_close(). We ensure to not
- * exceed CONF.MAX_RECURSION recursive levels. The supplied <tree> list_t
- * pointer should have been initialized using DLIST_INIT(). The tree_pool
- * pool_t should also have previously been initialized. Make sure to set the
- * global variable recursion_level to 0 before calling this function.
- */
-static int tree_open_r(list_t *tree, const char *dirpath, bool locking)
-{
-    list_t dir;
-    int error;
-
-    DLIST_INIT(&dir);
-    if ((error = dir_open(&dir, dirpath, locking)) == E_OK) {
-       struct tree_node *tnode;
-
-       if ((tnode = (struct tree_node *)pool_alloc(&tree_pool, FALSE))
-               != NULL) {
-           struct dir_node *dnode;
-
-           /* Append new tree node, from now on we are allowed to simply call
-            * tree_close() to safely release all acquired CVS locks.
-            */
-           tnode->namelen = mm_strncpy(tnode->name, dirpath, PATH_MAX - 1);
-           mm_memcpy(&tnode->dir, &dir, sizeof(list_t));
-           DLIST_APPEND(tree, (node_t *)tnode);
-           /* Recurse as necessary (and allowed) */
-           DLIST_FOREACH(&dir, dnode) {
-               if ((dnode->flags & DNF_DIRECTORY) != 0) {
-                   if (++recursion_level > CONF.MAX_RECURSION) {
-                       tree_close(tree, locking);
-                       return E_RLEVEL;
-                   }
-                   if ((error = tree_open_r(tree, dnode->name, locking))
-                           != E_OK) {
-                       tree_close(tree, locking);
-                       return error;
-                   }
-                   recursion_level--;
-               }
-           }
-       } else {
-           /* We could not record the entry for tree_close() yet, make sure
-            * to clear the CVS locks if needed for this dir_open().
-            */
-           if (locking) {
-               char buf[PATH_MAX];
-
-               (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.rfl.%d",
-                               dirpath, (int)pid);
-               (void) unlink(buf);
-               (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.lock", dirpath);
-               (void) rmdir(buf);
-           }
-           dir_close(&dir);
-           tree_close(tree, locking);
-           return E_NOMEM;
-       }
-    } else {
-       dir_close(&dir);
-       return error;
-    }
-
-    return E_OK;
-}
-
-
-/* Releases all successfully locked directories in the specified tree, as well
- * as all memory resources in use to cache it's filenames. The tree must
- * previously have been loaded using tree_open(). The tree_pool pool_t must
- * previously have been initialized.
- */
-static void tree_close(list_t *tree, bool locking)
-{
-    struct tree_node *tnode, *tmp;
-    char buf[PATH_MAX];
-
-    /* Can't use DLIST_FOREACH() as we're also freeing nodes */
-    for (tnode = DLIST_TOP(tree); tnode != NULL; tnode = tmp) {
-       tmp = DLIST_NEXT(tnode);
-       dir_close(&tnode->dir);
-       if (locking) {
-           (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.rfl.%d", tnode->name,
-                           (int)pid);
-           (void) unlink(buf);
-           (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.lock", tnode->name);
-           (void) rmdir(buf);
-       }
-       (void) pool_free((pnode_t *)tnode);
-    }
-    DLIST_INIT(tree);
-}
-
-
-/* Copies the contents of <srcpath> to <dstpath>, performing CVS locking
- * if CONF.CVS_LOCKING is enabled. Waits as required in bunches of
- * CONF.CVS_LOCK_DELAY seconds, upto a maximum of CONF.CVS_LOCK_TIMEOUT
- * seconds if necessary to obtain the read lock in a CVS-friendly manner.
- * Returns TRUE on success, or FALSE on error (which may leave a partial
- * tree copy dangling, this has to be handled by the caller).
- * Because this function is the one which may leave dangling lock files
- * if broken, we use gtree for "global tree" instead of a local tree variable
- * here, so that our SIGTERM handler may call tree_close() on it.
- */
-static bool tree_copy(const char *dstpath, const char *srcpath)
-{
-    int error;
-    long seconds = 0;
-    size_t srcpathlen = mm_strlen(srcpath);
-    bool cvs_locking = CONF.CVS_LOCKING;
-    bool displayed = FALSE;
-
-    for (;;) {
-       if ((error = tree_open(&gtree, srcpath, cvs_locking)) == E_LOCKED) {
-           if (seconds < CONF.CVS_LOCK_TIMEOUT) {
-               unsigned int s;
-
-               if (!displayed) {
-                   (void) fprintf(stderr, "Retrying for '%s' every %ld "
-                                  "seconds, for a maximum of %ld seconds, "
-                                  "because a CVS lock exists\n",
-                                  srcpath, CONF.CVS_LOCK_DELAY,
-                                  CONF.CVS_LOCK_TIMEOUT);
-                   (void) fflush(stderr);
-                   displayed = TRUE;
-               }
-               s = (unsigned int)CONF.CVS_LOCK_DELAY;
-               while (s != 0)
-                   s = sleep(s);
-               seconds += CONF.CVS_LOCK_DELAY;
-               continue;
-           } else {
-               (void) fprintf(stderr, "Exceeded maximum delay, proceeding "
-                              "anyways for '%s' despite the existing CVS "
-                              "lock\n",
-                              srcpath);
-               (void) fflush(stderr);
-               cvs_locking = FALSE;
-               continue;
-           }
-       } else if (error == E_OK) {
-           struct tree_node *tnode;
-
-           DLIST_FOREACH(&gtree, tnode) {
-               struct dir_node *dnode;
-
-               DLIST_FOREACH(&tnode->dir, dnode) {
-                   if (!file_copy(dnode, dstpath, srcpathlen)) {
-                       tree_close(&gtree, cvs_locking);
-                       return FALSE;
-                   }
-               }
-           }
-           tree_close(&gtree, cvs_locking);
-           break;
-       } else {
-           (void) fprintf(stderr, "tree_copy() - tree_open(%s) - (%s)\n",
-                          srcpath, STRERROR(error));
-           return FALSE;
-       }
-    }
-
-    return TRUE;
-}
-
-
-/* Copies the file specified by the dir_node <dnode> entry, assumed to be
- * an absolute pathname starting with <origrootlen> characters, into the
- * specified <destroot>. It can also create a directory instead if the entry
- * consists of one. It ensures to set safe creation permission modes.
- * The way we transform the absolute pathname to migrate from <origroot>,
- * which was the directory supplied at tree_open(), to <destroot>, is as
- * follows:
- * - <origrootlen> is used to know how many characters to strip from
- *   dnode->name. This pathname never has a trailing '/', but always starts
- *   with one.
- * - A buffer is created with the new destination consisting of <destroot>
- *   followed by the remaining characters of dnode->name. <destroot> will
- *   consist of an absolute pathname to a temporary directory. <destroot>
- *   never has a trailing '/', but always starts with one.
- */
-static bool file_copy(struct dir_node *dnode, const char *destroot,
-       size_t origrootlen)
-{
-    char buf[PATH_MAX];
-    bool ok = FALSE;
-
-    (void) snprintf(buf, PATH_MAX - 1, "%s%s", destroot,
-                   &dnode->name[(int)origrootlen]);
-    if ((dnode->flags & DNF_DIRECTORY) != 0) {
-       /* Directory entry, create it */
-       if (mkdir(buf, 0755) == -1) {
-           (void) fprintf(stderr, "file_copy() - mkdir(%s) - (%s)\n",
-                          buf, strerror(errno));
-       } else
-           ok = TRUE;
-       if (!mm_chgrp(buf))
-           ok = FALSE;
-    } else {
-       int sfd, dfd;
-
-       /* File entry, copy it */
-       if ((sfd = open(dnode->name, O_RDONLY)) != -1) {
-           if ((dfd = open(buf, O_CREAT | O_WRONLY,
-                           (((dnode->flags & DNF_EXECUTABLE) != 0) ?
-                            0744 : 0644)))
-                   != -1) {
-               ssize_t len;
-
-               ok = TRUE;
-               while ((len = read(sfd, copybuf, COPYBUF_SIZE)) != 0) {
-                   if (len == -1) {
-                       (void) fprintf(stderr, "file_copy() - read(%s) - (%s)",
-                                      dnode->name, strerror(errno));
-                       ok = FALSE;
-                       break;
-                   }
-                   if (write(dfd, copybuf, len) != len) {
-                       (void) fprintf(stderr,
-                                      "file_copy() - write(%s) - (%s)",
-                                      buf, strerror(errno));
-                       ok = FALSE;
-                       break;
-                   }
-               }
-               if (close(dfd) == -1) {
-                   (void) fprintf(stderr, "file_copy() - close(%s) - (%s)",
-                                  buf, strerror(errno));
-                   ok = FALSE;
-               }
-           }
-           (void) close(sfd);
-       }
-    }
-
-    return ok;
-}
-
-
-/* Attempts to recursively delete the specified directory along with it's
- * contents. It relies on the same tree_open() function which deals with the
- * only files which should ever be created in our temporary directories. This
- * is also subject to the CONF.MAX_RECURSION limit for more safety. As we
- * created the temporary directory with the same system, this should work
- * fine, while being safer than a standard recursive delete operation. We
- * obviously do not use CVS locking here, however. This is pretty safe as it
- * will only accept to delete "*,v" RCS files and will not follow symbolic
- * links. It always uses the fullpath for unlink(2)/rmdir(2).
- * Only used to delete the temporary directory when the mirror operation
- * fails for a reason or another. Normally, a single rename(2) operation
- * replaces the old cvsroot by the temporary directory instead.
- */
-static bool tree_delete(const char *dirpath)
-{
-    list_t tree;
-    int error;
-    struct tree_node *tnode;
-    struct dir_node *dnode;
-    long oldcnt, newcnt;
-
-    if ((error = tree_open(&tree, dirpath, FALSE)) != E_OK) {
-       (void) fprintf(stderr, "tree_delete() - tree_open(%s) - (%s)",
-                      dirpath, STRERROR(error));
-       return FALSE;
-    }
-
-    /* First delete all files, but also count directories. If an error
-     * occurs, there is no point in continueing, just log and stop then.
-     */
-    oldcnt = 0;
-    newcnt = -1;
-    DLIST_FOREACH(&tree, tnode) {
-       DLIST_FOREACH(&tnode->dir, dnode) {
-           if ((dnode->flags & DNF_DIRECTORY) == 0) {
-               if (unlink(dnode->name) == -1) {
-                   (void) fprintf(stderr,
-                                  "tree_delete() - unlink(%s) - (%s)\n",
-                                  dnode->name, strerror(errno));
-                   goto end;
-               }
-           } else
-               oldcnt++;
-       }
-    }
-
-    /* And now delete all directories. To avoid needing to sort a tree,
-     * we only re-iterate if directory not empty errors occur, but
-     * stopping if we notice that the number of directories in the tree
-     * does not decrease. We stop if any other error than ENOTEMPTY occurs.
-     */
-    for (; oldcnt > 0; oldcnt = newcnt) {
-       newcnt = 0;
-       DLIST_FOREACH(&tree, tnode) {
-           DLIST_FOREACH(&tnode->dir, dnode) {
-               if ((dnode->flags & DNF_DIRECTORY) != 0) {
-                   newcnt++;
-                   if (rmdir(dnode->name) == 0) {
-                       newcnt--;
-                       dnode->flags &= ~DNF_DIRECTORY;
-                   } else {
-                       if (errno != ENOTEMPTY) {
-                           (void) fprintf(stderr,
-                                       "tree_delete() - rmdir(%s) - (%s)\n",
-                                       dnode->name, strerror(errno));
-                           goto end;
-                       }
-                   }
-               }
-           }
-       }
-       if (newcnt == oldcnt) {
-           /* There obviously is a problem here, stop iterating. */
-           break;
-       }
-    }
-
-end:
-    tree_close(&tree, FALSE);
-
-    return (newcnt == 0 ? TRUE : FALSE);
-}
-
-
-/* Used to ensure that the group of the created readonly repository files
- * be set to CONF.REPGROUP. This is necessary for instance to restrict the
- * writers to the val-tags file in CVSROOT/ which CVS pserver requires write
- * access to (but should not be allowed to delete).
- */
-static bool mm_chgrp(const char *filepath)
-{
-    if (chown(filepath, -1, repgroup) == -1) {
-       (void) fprintf(stderr, "mm_chgrp() - chown(%s, -1, %d) - (%s)\n",
-                      filepath, repgroup, strerror(errno));
-       return FALSE;
-    }
-
-    return TRUE;
-}
diff --git a/mmsoftware/mmanoncvs/mmanoncvs.conf.5 b/mmsoftware/mmanoncvs/mmanoncvs.conf.5
deleted file mode 100644 (file)
index 0e68739..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-.\" $Id: mmanoncvs.conf.5,v 1.6 2004/04/30 00:01:18 mmondor Exp $
-.\"
-.\" Copyright (C) 2003-2004, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\" 5. Redistribution of source code may not be released under the terms of
-.\"    any GNU Public License derivate.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd November 9, 2003
-.Dt MMANONCVS.CONF 5
-.Os mmsoftware
-.Sh NAME
-.Nm mmanoncvs.conf
-.Nd
-.Xr mmanoncvs.conf 5
-configuration file for
-.Xr mmanoncvs 8
-.Sh DESCRIPTION
-The
-.Nm /usr/local/etc/mmanoncvs.conf
-file may contain one or more keyword/value pairs per line, empty lines or
-comments.  A ';' or '#' character causes all other characters to be considered
-as a comment, and to be ignored, until the end of the current line. It is
-very important to enclose the value for a keyword in double quotes ('"'
-characters) if the following characters are found in it: ';', '#', space and
-tab. It is allowed to use an equal sign '=' between the keyword name and it's
-argument. Here are documented the various possible keywords and their
-allowed values, as well as their defaults.
-.Ss Privilege revokation parameters
-.Bl -tag -width indent -offset indent
-.It Nm DROP_PRIVS Ar "boolean"
-This is most useful when
-.Xr mmanoncvs 8
-is launched by the superuser. This is often the case when launched by the
-system cron event scheduler for instance. Should be TRUE or FALSE. Set to
-FALSE if the program is launched by an unprivileged user.
-.It Nm USER Ar "user"
-Only taken in consideration if
-.Nm DROP_PRIVS
-is TRUE. Specifies the user which should be revoked superuser privileges to.
-.It Nm GROUPS Ar "group,..."
-Also only of interest if
-.Nm DROP_PRIVS
-is TRUE, specifies a comma-separated list of groups which we should be part of
-after revoking privileges.
-.It Nm REPGROUP Ar "group"
-Always taken into consideration, this specifies the group which should be set
-to all created files in the destination repository. Obviously, if not running
-as the superuser, this group also should be specified in
-.Nm GROUPS 
-if
-.Nm DROP_PRIVS
-is TRUE, or the unprivileged user launching
-.Xr mmanoncvs 8
-should be part of that group. Otherwise, permission denied errors will occur.
-.El
-.Ss Lock related parameters
-.Bl -tag -width indent -offset indent
-.It Nm LOCK_PATH Ar "fullpath"
-Specifies the full path to a file to be used to prevent self-recursion.
-.Xr mmanoncvs 8
-refuses to run if this lock is held by an already executing instance.
-.It Nm ALOCK_LOCKING Ar "boolean"
-If TRUE, the program will attempt to use
-.Xr flock 2
-on the
-.Nm ALOCK_PATH
-file (see below). This is provided so that if FALSE is used, this program
-can run standalone (without requireing
-.Xr mmspawnd 8 ) .
-Enabling concurrency locking and using
-.Xr mmspawnd 8
-is highly recommended.
-.It Nm ALOCK_PATH Ar "fullpath"
-This is for
-.Xr mmanoncvs 8
-to work in conjunction with
-.Xr mmspawnd 8
-for live setups with concurrency. When updating the destination anoncvs
-pserver repository, locking this file using
-.Xr flock 2
-permits to make the operation atomic to pserver users. This way we prevent
-inconsistent CVS repository checkouts/updates.
-.It Nm CVS_LOCKING Ar "boolean"
-If TRUE, CVS-friendly locking will be performed on the source repositories
-when doing the mirror, so that concurrency with existing CVS commands on
-the read/write repository is safe while running
-.Xr mmanoncvs 8
-to create/update the read-only pserver repository. Use of this option is
-recommended to prevent the pserver repository from being inconsistent.
-With this, a source repository maintainer may commit change safely, and
-the backup will occur after it completed the commit, for instance, and
-then prevent commits until the backup is complete.
-.Pp
-Although using this option is encouraged, there are two things to take
-into consideration. First, The
-.Xr mmanoncvs 8
-program must run with the appropriate permissions to be able to write
-to the source repositories to create the temporary directory and file
-locks. There are various ways to achieve this, either running it as
-the superuser or as an unprivileged user.
-.Pp
-The second fact to consider is that source repositories should not set an
-alternate LockDir option in their CVSROOT/config file (which would cause the
-locks to not be able to compete with eachother, relying on different
-locations). Because
-.Xr mmanoncvs 8
-works with CVS repository directories rather than actual CVS repositories,
-allowing it to be more powerful about what to merge together into the
-destination pserver repository, it cannot track which CVSROOT directory
-belongs to which source directory to be able to also honor alternate LockDir.
-Fortunately, this LockDir option is very seldom used, and the CVS locks
-are always created in the repository directories by default.
-.It Nm CVS_LOCK_DELAY Ar "seconds"
-When
-.Nm CVS_LOCKING
-is enabled, this specifies the number of seconds to wait until re-attempting,
-if the source repository is currently locked. The way CVS locking works is as
-follows: An attempt to obtain locks on all involved directories recursively
-is made. If a lock exists in any of those directories, we must release all
-successfully acquired locks to prevent deadlocks. We then wait
-.Nm CVS_LOCK_DELAY
-seconds, and retry, upto a maximum of
-.Nm CVS_LOCK_TIMEOUT ,
-at which point the offending lock(s) are considered to be stalled locks and
-normal operations resume.
-.Pp
-See the CVS documentation for more information, in the concurrency and locking
-sections, and about #cvs.lock master lock directories and #cvs.rfl.* read
-locks files.
-.It Nm CVS_LOCK_TIMEOUT Ar "seconds"
-When
-.Nm CVS_LOCKING
-is enabled, this specifies the maximum allowed number of seconds to wait on
-a existing lock in a source repository before considering the lock(s) stalled,
-when we should be resuming the backup anyways.
-.El
-.Ss Directory related parameters
-.Bl -tag -width indent -offset indent
-.It Nm REPDIR Ar "directory"
-Should specify an absolute directory pathname to the directory. All destination
-directories specified in
-.Xr mmanoncvs.list 5
-will be inside this directory. This typically is "/var/anoncvs/cvsroot", for
-instance. It is important that
-.Xr mmanoncvs 8
-be able to write to this directory. It in fact should be owned by the user
-under which it will run. Moreover, the directory in which
-.Nm REPDIR
-is located should also be writable. See the
-.Xr mmanoncvs 8
-manual page section about
-.Xr chroot 2
-setup with
-.Xr mmspawnd 8
-for more details.
-Note that a CVSROOT directory is automatically created with the proper
-configuration for
-.Xr mmspawnd 8
-and
-.Xr cvs 1
-pserver in that directory when a successful mirror is done.
-.It Nm TMPDIR Ar "directory"
-An absolute directory pathname to a temporary directory on the same filesystem
-as
-.Xr REPDIR ,
-used to store temporary directories and files when performing a mirror of
-the CVS repositories. This directory should be writable by
-.Xr mmanoncvs 8
-as well.
-.El
-.Ss Other backup control parameters
-.Bl -tag -width indent -offset indent
-.It Nm LISTFILE Ar "fullpath"
-An absolute pathname to a file which should be in the
-.Xr mmanoncvs.list 5
-format. This file will be read to tell what to copy and where. Please
-see the corresponding manual page for more details.
-.It Nm MAX_RECURSION Ar "number"
-Specifies the maximum number of directory levels allowed for recursive
-copy of source directories specified in
-.Nm LISTFILE .
-This should be high enough to allow normal operation, but low enough to
-prevent hugging the system for a long while with high CPU load caused by
-malicious directory hard links in the source repository.
-.It Nm MAX_FILESIZE Ar "number"
-Specifies the maximum allowed files to copy, in bytes. Files which exceed
-this value are ignored (and a message is logged).
-.It Nm KEEP_EXEC Ar "boolean"
-If TRUE, this parameter specifies that the executable bit on RCS files within
-a CVS repository to be copied should be preserved in the destination. This is
-most useful because of shell building and configuration scripts which are often
-found in projects, such as
-.Nm build.sh
-or
-.Nm configure .
-Note that if this feature is enabled, only the owner of the file will be
-set the executable bit (which consists of the user running
-.Xr mmanoncvs 8
-and owning the
-.Nm /cvsroot
-directory into the anonymous pserver root directory).
-.Pp
-This prevents the commands ran into the chroot setup, such as
-.Xr cvs 1
-executable, or other users which have read access to the backup tree, from
-being able to execute those files. This way it is safe to preserve the
-executable bit of arbitrary files without causing security issues.
-However, it is the responsibility of the administrator to ensure that the
-user running
-.Xr mmanoncvs 8
-consists of the superuser or of a dedicated user without shell access, and
-that
-.Xr mmspawnd 8
-is set to run under a different unprivileged user than that owning the
-.Nm /cvsroot
-directory, as usual.
-.El
-.Sh DEFAULTS
-The following defaults are used:
-.Pp
-.Bd -literal -offset indent
-DROP_PRIVS             FALSE
-USER                   anoncvsa
-GROUPS                 anoncvs,users
-REPGROUP               anoncvs
-
-LOCK_PATH              /tmp/mmanoncvs.lock
-ALOCK_LOCKING          TRUE
-ALOCK_PATH             /var/run/mmspawnd-anoncvs.alock
-CVS_LOCKING            TRUE
-CVS_LOCK_DELAY         30
-CVS_LOCK_TIMEOUT       300
-
-REPDIR                 /var/anoncvs/cvsroot
-TMPDIR                 /var/anoncvs/tmp
-
-LISTFILE               /usr/local/etc/mmanoncvs.list
-MAX_RECURSION          20
-MAX_FILESIZE           2147483647
-KEEP_EXEC              TRUE
-.Ed
-.Sh AUTHOR
-.Nm mmanoncvs
-was written by Matthew Mondor, and is
-Copyright (c) 2003-2004, Matthew Mondor, All rights reserved.
-.Sh FILES
-.Bl -tag -width indent -offset indent
-.It Pa /usr/local/etc/mmanoncvs.conf
-This file
-.It Pa /usr/local/etc/mmanoncvs.list
-The
-.Xr mmanoncvs.list 5
-configuration file
-.It Pa /usr/local/sbin/mmanoncvs
-The
-.Xr mmanoncvs 8
-binary itself.
-.El
-.Sh SEE ALSO
-.Xr mmanoncvs 8 ,
-.Xr mmanoncvs.list 5 ,
-.Xr mmspawnd 8 ,
-.Xr chroot 2 ,
-.Xr flock 2 ,
-.Xr cvs 1 .
-.Sh BUGS
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/mmanoncvs/mmanoncvs.list.5 b/mmsoftware/mmanoncvs/mmanoncvs.list.5
deleted file mode 100644 (file)
index 0d67e49..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-.\" $Id: mmanoncvs.list.5,v 1.5 2004/04/30 00:01:18 mmondor Exp $
-.\"
-.\" Copyright (C) 2003-2004, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\" 5. Redistribution of source code may not be released under the terms of
-.\"    any GNU Public License derivate.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd November 9, 2003
-.Dt MMANONCVS.LIST 5
-.Os mmsoftware
-.Sh NAME
-.Nm mmanoncvs.list
-.Nd
-.Xr mmanoncvs.list 5
-configuration file for
-.Xr mmanoncvs 8 .
-.Sh DESCRIPTION
-The
-.Nm /usr/local/etc/mmanoncvs.list
-file serves to describe which CVS repositories (or which directories of which
-repositories) to backup into the anoncvs read-only repository, usually for
-access using
-.Xr mmspawnd 8 .
-.Ss File format
-.Pp
-The format of this file is very simple. Blank lines and lines which have the
-first printable character as ';' or '#' are ignored. Other lines are expected
-to only contain two space or tab separated columns. Every of the two columns
-may use single quotes (') as required if spaces are found in the elements.
-.Pp
-Each column element must consist of an absolute directory pathname, beginning
-with '/'. Trailing '/', if any, are ignored, and multiple consecutive '/' into
-a pathname are considered like a single one like POSIX suggests.
-.Pp
-The first column specifies the destination directory into
-.Nm REPDIR
-(See
-.Xr mmanoncvs.conf 5 ) ,
-and the second column from which directory to recursively copy files into
-the directory represented by the first column. It is valid to use "/" in the
-first (destination) column, to specify that the files in the second (source)
-column directory be copied recursively into
-.Nm REPDIR
-directly. Otherwise, the specified extra directories are created in
-.Nm REPDIR ,
-and the files in the source directory copied in that directory.
-.Pp
-Each line is thus considered as a copy operation which will be performed,
-sequencially, in the specified order. It is the responsibility of the
-administrator to avoid directory name conflicts or duplicate copies.
-.Pp
-Note that files and directories starting with 'CVS' are ignored, which
-allows to use any directory, be it the root to several CVS repositories
-each with their CVSROOT, a single directory of a repository, or an actual
-repository root directory.
-.Ss Example configuration files
-.Pp
-Here is a first example:
-.Bd -literal -offset indent
-# We have many projects in /var/cvs which each have their
-# directory. We want them to be accessible directly under
-# /cvsroot for pserver access:
-/      /var/cvs
-.Ed
-.Pp
-And another example:
-.Bd -literal -offset indent
-# Lucca's projects
-/users/lucca   /home/admin/lucca/cvsroot
-
-# Matt's
-/users/mmondor /home/users/mmondor/cvsroot
-
-# Rohit's
-/users/rohit   /home/users/rohit/cvsroot
-
-# Common projects
-/common                /var/cvs
-.Ed
-.Sh DEFAULTS
-None
-.Sh AUTHOR
-.Nm mmanoncvs
-was written by Matthew Mondor, and is
-Copyright (c) 2003-2004, Matthew Mondor, All rights reserved.
-.Sh FILES
-.Bl -tag -width indent -offset indent
-.It Pa /usr/local/etc/mmanoncvs.list
-This file
-.It Pa /usr/local/etc/mmanoncvs.conf
-.Xr mmanoncvs.conf 5
-file for
-.Xr mmanoncvs 8
-.It Pa /usr/local/sbin/mmanoncvs
-The
-.Xr mmanoncvs 8
-binary itself.
-.El
-.Sh SEE ALSO
-.Xr mmanoncvs 8 ,
-.Xr mmspawnd 8 ,
-.Xr mmanoncvs.conf 5 .
-.Sh BUGS
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/mmidentd/GNUmakefile b/mmsoftware/mmidentd/GNUmakefile
deleted file mode 100644 (file)
index fafd9ec..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# $Id: GNUmakefile,v 1.1 2004/05/05 10:08:46 mmondor Exp $
-
-OBJS := mmidentd.o
-
-CFLAGS += -Wall
-
-
-all: mmidentd
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -o $@ $<
-
-mmidentd: $(MMLIBS) $(OBJS)
-       cc -o $@ -lc $(OBJS)
-
-install:
-       install -cs -o 0 -g 0 -m 550 mmidentd /usr/local/libexec
-#      install -c -o 0 -g 0 -m 444 mmidentd.8 /usr/local/man/man8
-
-clean:
-       rm -f mmidentd $(OBJS)
diff --git a/mmsoftware/mmidentd/mmidentd.c b/mmsoftware/mmidentd/mmidentd.c
deleted file mode 100644 (file)
index 042f732..0000000
+++ /dev/null
@@ -1,323 +0,0 @@
-/* $Id: mmidentd.c,v 1.3 2004/04/30 00:01:18 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * mmidentd - A simple random ident server
- * Copyright (c) 2003, Matthew Mondor,
- * ALL RIGHTS RESERVED.
- *
- * This is expected to be installed as /usr/local/libexec/mmidentd and to be
- * launched as required by the inetd server, under an unprivileged user.
- * The only required argument consists of the dictionary to extract random
- * words from.
- * An example configuration line for /etc/inetd.conf follows:
- *
- * ident stream tcp nowait nobody:nogroup /usr/local/libexec/mmidentd \
- *   mmidentd /usr/share/dict/words
- *
- * The way this program works is simple. It uses the supplied dictionary and
- * to efficiently choose a random word, then reverses it and converts it to
- * lowercase. Only words within 3 to 10 characters in length will be used.
- * Words are expected to be separated by any ASCII character below 33, which
- * includes spaces, tabs, '\r' and '\n' characters. The size of the dictionary
- * file can reach the maximum limit which the filesystem or OS allows. On BSD
- * systems, 64-bit is used by default for filesystem offsets which allows
- * very large files to be used.
- *
- * This program uses the "/dev/urandom" device, if present, to seed the pseudo
- * random number generator, but will fall back to using time(2) for seeding
- * if that device cannot be found or used. The 4.2BSD random(3) PRNG is used
- * over rand(3) for best results. Using this technique, it is unlikely that
- * a peer could evaluate the current state of the OS PRNG device, and the
- * results are rather good still.
- *
- * If errors occur, the 'unknown' user response will always be issued.
- * This can happen if the two required file parameter is missing or wrong,
- * if the file cannot be found, or if mapping problems exist.
- *
- * I previously wrote other random ident servers, the first one used to
- * alternate one vowel and one consonant, using random for the response length
- * and which of the character classes to begin with. The second was similar
- * but occasionally allowed two contiguous non-identical vowels plus two
- * occasional contiguous 'o' vowels, so that it generated more plausible
- * "words". However, if a dictionary is available, the words are bound to
- * even be more plausible :), and when reverted it prevents some of those
- * words from being offensive (which could be the case using a standard
- * dictionary), and provides an interesting effect.
- *
- * For optimum performance, this program uses a single open(2)/mmap(2) pass
- * to access the dictionary. This allows mapping the whole file virtually
- * into the process, but the pages which actually need to be imported into
- * the process space are the ones we perform accesses to (generally one page
- * only being faulted in when a proper dictionary is provided). Moreover,
- * only pages which weren't recently used need to be read from disk, and that's
- * also generally one single page. If you experience that this is not the case,
- * perhaps consider using a proper 3-10 character words dictionary, and running
- * NetBSD :)
- *
- * It would not have been possible to use the ANSI stdio and achieve the same
- * performance. First, it uses it's own memory buffers, which obviously need
- * to be allocated into the process's space. Second, it attempts to use that
- * buffering, resulting in many unnecessary memory copy operations. Moreover,
- * we would need to perform random access reads, which mostly discard the
- * purpose of using stdio. It would work, however. It would just have been
- * both more of a hassle to write and slower. Anyways, libc stdio is just
- * another layer which needs to use the unix system calls underneath, and
- * this program is intended for unix systems. We actually don't use stdio
- * at all in this very simple program.
- *
- * This program should be fairly small when compiled statically. This may be
- * wanted to speed up application launching time, or to make it independant
- * of the C library. Results in a 16k static executable on NetBSD after
- * stripping. This small size is again caused by the stdio avoidance.
- */
-
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <poll.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-
-
-
-#define RANDDEV                "/dev/urandom"
-#define NULLDEV                "/dev/null"
-#define DEFAULT                "unknown"
-#define BUFSIZE                32
-#define RBUFSIZE       64
-#define RETRIES                64
-#define TIMEOUT                30
-#define ISCHAR(c)      isprint(c)
-
-
-
-int main(int, char **);
-static void randinit(void);
-static void strrevtolower(char *);
-
-
-
-int main(int argc, char **argv)
-{
-    int fd, nfd;
-    size_t ilen;
-    char ident[BUFSIZE], buf[BUFSIZE];
-    struct pollfd pfd[] = {
-       {0, POLLIN | POLLHUP | POLLERR, 0}
-    };
-
-    nfd = open(NULLDEV, O_RDWR);
-
-    /* For safety, get rid of stderr. */
-    if (nfd != -1)
-       (void) dup2(nfd, 2);
-
-    /* Initialize the default response and the PRNG. */
-    (void) memcpy(ident, DEFAULT, sizeof(DEFAULT));
-    ident[sizeof(DEFAULT)] = '\0';
-    ilen = sizeof(DEFAULT);
-    randinit();
-
-    /* If any of the following block fails, DEFAULT response will be issued.
-     */
-    if (argc == 2 && (fd = open(argv[1], O_RDONLY)) != -1) {
-       struct stat st;
-       u_int32_t fsize;
-       char *dict;
-
-       if (fstat(fd, &st) == 0) {
-           fsize = (u_int32_t)st.st_size;
-           if ((dict = mmap(NULL, (size_t)fsize, PROT_READ,
-                           MAP_FILE | MAP_PRIVATE, fd, (off_t)0))
-                   != MAP_FAILED) {
-               int tries;
-               size_t len;
-               /* Start, Center and End pointers */
-               register char *sptr, *cptr, *eptr, *tptr;
-
-#ifndef __GLIBC__
-               /* On BSD systems, inform the VM of the fact that we'll
-                * access random pages, for optimum performance.
-                */
-               (void) madvise(dict, (size_t)fsize, MADV_RANDOM);
-#endif /* __GLIBC__ */
-
-               /* Not to reach end pointer */
-               tptr = dict + fsize;
-               /* Loop until we exceeded the number of retries or until we
-                * obtained a valid word to use
-                */
-               for (tries = 0, len = 0;
-                       tries < RETRIES && (len < 3 || len > 10); tries++) {
-                   /* Slice the file randomly with cptr */
-                   cptr = dict + (random() % fsize);
-                   /* Run left from cptr with sptr */
-                   for (sptr = cptr; sptr >= dict && ISCHAR(*sptr); sptr--) ;
-                   if (!ISCHAR(*sptr))
-                       sptr++;
-                   /* And right from cptr with eptr */
-                   for (eptr = cptr; eptr < tptr && ISCHAR(*eptr); eptr++) ;
-                   /* We now have a word, evaluate it's length. */
-                   len = eptr - sptr;
-               }
-               if (tries < RETRIES) {
-                   /* It seems that we isolated a proper word. Generate the
-                    * ident response string with it, to replace the default
-                    * DEFAULT one.
-                    */
-                   (void) memcpy(ident, sptr, len);
-                   ident[len] = '\0';
-                   strrevtolower(ident);
-                   ilen = len;
-               }
-               (void) munmap(dict, (size_t)fsize);
-           }
-       }
-       (void) close(fd);
-    }
-
-    /* Now query other end for the 'port, port' string request.
-     * We could setup a timer here, and use fgets(2). But as unix uses line
-     * buffering by default, and that poll(2) will nicely respect a timeout,
-     * let's again avoid stdio, which by the way calls extraneous syscalls,
-     * including initialization of the malloc(3) system, which in turn can
-     * call a bunch of brk(2) :) So let's add a few minutes of coding to save
-     * many minutes of accumulated CPU time during the very successfull
-     * years of serving using this identd! (sarcasm)
-     */
-    if ((poll(pfd, 1, TIMEOUT * 1000)) == 1 && ((*pfd).revents & POLLIN)) {
-       size_t len;
-
-       if ((len = read(0, buf, BUFSIZE - 1)) > 0) {
-           register char *ptr, *tptr, *aptr, *bptr;
-           size_t alen, blen;
-           char out[64];
-
-           buf[len] = '\0';
-           /* We don't need input anymore */
-           if (nfd != -1)
-               (void) dup2(nfd, 0);
-
-           /* Parse port numbers. We do not even need to perform any ASCII to
-            * decimal convertion.
-            */
-           tptr = buf + len;
-           for (ptr = buf; ptr < tptr && !isdigit(*ptr); ptr++) ;
-           for (aptr = ptr; ptr < tptr && isdigit(*ptr); ptr++) ;
-           for (alen = ptr - aptr; ptr < tptr && !isdigit(*ptr); ptr++) ;
-           for (bptr = ptr; ptr < tptr && isdigit(*ptr); ptr++) ;
-           blen = ptr - bptr;
-
-           /* Now generate our very authentic output response, and send it.
-            * We substitute 0 for reply port numbers if the parsed ones were
-            * illegal or missing.
-            */
-           ptr = out;
-           if (alen > 0 && alen < 6) {
-               (void) memcpy(ptr, aptr, alen);
-               ptr += alen;
-           } else
-               *ptr++ = '0';
-           *ptr++ = ' ';
-           *ptr++ = ',';
-           *ptr++ = ' ';
-           if (blen > 0 && blen < 6) {
-               (void) memcpy(ptr, bptr, blen);
-               ptr += blen;
-           } else
-               *ptr++ = '0';
-           (void) memcpy(ptr, " : USERID : UNIX : ", 19);
-           ptr += 19;
-           (void) memcpy(ptr, ident, ilen);
-           ptr += ilen;
-           *ptr++ = '\r';
-           *ptr++ = '\n';
-           *ptr = '\0';
-           (void) write(1, out, (size_t)(ptr - out));
-       }
-    }
-
-    if (nfd != -1)
-       (void) close(nfd);
-
-    return 0;
-}
-
-
-/* First attempts to seed the 4.2BSD random number generator using the
- * "/dev/urandom" device. If we cannot, falls back to simple time-dependent
- * seeding.
- */
-static void randinit(void)
-{
-    int fd, ok = -1;
-
-    if ((fd = open(RANDDEV, O_RDONLY)) != -1) {
-       unsigned long s;
-
-       if ((read(fd, &s, sizeof(unsigned long))) == sizeof(unsigned long)) {
-           srandom(s);
-           ok = 0;
-       }
-       (void) close(fd);
-    }
-    if (ok == -1)
-       srandom((unsigned long)time(NULL));
-}
-
-
-/* Reverses the supplied string, but also converts it to lowercase. */
-static void strrevtolower(char *str)
-{
-    register char *p1, *p2, t;
-
-    for (p1 = p2 = str; *p2 != '\0'; p2++)
-       *p2 = (char)tolower(*p2);
-    if (p2 > p1)
-       p2--;
-
-    for (; p1 < p2; p1++, p2--) {
-       t = *p1;
-       *p1 = *p2;
-       *p2 = t;
-    }
-}
diff --git a/mmsoftware/mmmail2/ChangeLog b/mmsoftware/mmmail2/ChangeLog
deleted file mode 100644 (file)
index 96ed104..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-$Id: ChangeLog,v 1.1 2002/12/11 10:16:56 mmondor Exp $
-
-
-
diff --git a/mmsoftware/mmmail2/README b/mmsoftware/mmmail2/README
deleted file mode 100644 (file)
index 2d55c7b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-$Id: README,v 1.1 2002/12/11 10:16:56 mmondor Exp $
-
-
-
-This is no way complete, nor supposed to be functional, yet.
-Here are current design draft notes and test programs for the future mmmail2
-(version 2) which consists of a complete re-implementation of mmmail.
-
-The goal is to provide all necessary features of mail-related software,
-and various data storage methods (db4 and file to SQL).
-
-Please see the notes/ directory documents for more details.
-
-Matt
diff --git a/mmsoftware/mmmail2/notes/convert.sh b/mmsoftware/mmmail2/notes/convert.sh
deleted file mode 100755 (executable)
index 408227c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# First export LyX document to LaTeX then run this script
-
-latex mmmail-design.tex
-rm -f mmmail-design.ps mmmail-design.aux mmmail-design.log
-dvips -o mmmail-design.ps -t letter -D 300 -Z mmmail-design.dvi
-ps2pdf mmmail-design.ps
-rm -f *~
diff --git a/mmsoftware/mmmail2/notes/mmmail-design.lyx b/mmsoftware/mmmail2/notes/mmmail-design.lyx
deleted file mode 100644 (file)
index d1dc11d..0000000
+++ /dev/null
@@ -1,875 +0,0 @@
-#LyX 1.2 created this file. For more info see http://www.lyx.org/
-\lyxformat 220
-\textclass article
-\language english
-\inputencoding auto
-\fontscheme default
-\graphics default
-\paperfontsize default
-\spacing single 
-\papersize letterpaper
-\paperpackage a4
-\use_geometry 1
-\use_amsmath 0
-\use_natbib 0
-\use_numerical_citations 0
-\paperorientation portrait
-\leftmargin 1in
-\topmargin 0.5in
-\rightmargin 1in
-\bottommargin 0.5in
-\secnumdepth 3
-\tocdepth 3
-\paragraph_separation indent
-\defskip medskip
-\quotes_language english
-\quotes_times 2
-\papercolumns 1
-\papersides 1
-\paperpagestyle default
-
-\layout Title
-
-mmmail v2 project design (draft 3)
-\layout Author
-
-By Matthew Mondor
-\layout Abstract
-
-
-\series bold 
-mmmail
-\series default 
- is currently being redesigned from scratch to support new features which
- the current design could not be easily adapted to provide.
- This design is intended for a new branch, 
-\series bold 
-mmmail
-\series default 
- version 2.
-\layout Abstract
-
-
-\series bold 
-mmmail
-\series default 
-, along with this document, are Copyright (c) 2001-2002, Matthew Mondor,
- All rights reserved.
-\layout Abstract
-
-The status of 
-\series bold 
-mmmail
-\series default 
- version 2, and it's design is currently under development.
- If you can provide any bug report or suggestions about the design, please
- contact Matthew Mondor, via email at 
-\series bold 
-mmondor@gobot.ca
-\layout Section
-
-Targetted features
-\layout Standard
-
-
-\series bold 
-mmmail
-\series default 
- version 2 should support the following features.
-\layout List
-\labelwidthstring 00.00.0000
-
-Domain\SpecialChar ~
-administration\SpecialChar ~
-delegation: It should be possible for the system manager
- to delegate administration tasks to administrators of particular domains.
- In the new design administrators can be specified domains they can manage,
- and various access permissions can be customized per administrator.
-\layout List
-\labelwidthstring 00.00.0000
-
-Mail\SpecialChar ~
-filtering: Mail should be able to optionally be filtered when getting
- in through SMTP before being routed into mailboxes or relayed out.
-\layout List
-\labelwidthstring 00.00.0000
-
-SMTP\SpecialChar ~
-relaying: The current released 
-\series bold 
-mmmail
-\series default 
- implementation does not allow relaying messages at all.
- The new design should allow it.
- It appears to be the most requested feature which alot of users need.
- It should relay using smarthosts or MX routing.
-\begin_deeper 
-\layout Itemize
-
-
-\emph on 
-Design for the smarthosts part not yet complete.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-Bandwidth\SpecialChar ~
-shaping: 
-\series bold 
-mmmail
-\series default 
- should continue to support per-connection and global read and write bandwidth
- speed limits.
-\layout List
-\labelwidthstring 00.00.0000
-
-POP3: 
-\series bold 
-mmmail
-\series default 
- already supports POP3 since the start, and should continue supporting it.
- The APOP extension could be supported, however this unfortunately requires
- passwords to be stored in clean text into the user database rather than
- as hashes.
-\layout List
-\labelwidthstring 00.00.0000
-
-IMAP: The second most requested feature consists of IMAP support.
- I intend to design the new system in a way to allow making this possible.
-\layout List
-\labelwidthstring 00.00.0000
-
-IMAP-SMTP\SpecialChar ~
-and\SpecialChar ~
-POP3-SMTP: Several times when request was made about relaying,
- mention was done about this technique; Relaying from a host would be accepted
- during a customizable delay (possibly also for a customizable maximum number
- of messages), after a user has successfully authenticated via POP3 or IMAP.
-\layout List
-\labelwidthstring 00.00.0000
-
-Per-mailbox\SpecialChar ~
-auto-forwarding: This feature will allow users to auto-forward
- all incomming mail for a mailbox to another email address, if relaying
- is allowed for that domain, of course.
-\begin_deeper 
-\layout Itemize
-
-
-\emph on 
-Design for this not yet complete, should use permissions.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-Mailing\SpecialChar ~
-list\SpecialChar ~
-management: It should be possible for 
-\series bold 
-mmmail
-\series default 
- to have mailboxes in fact consisting of mailing lists, for which a list
- of subscribed addreses would be kept.
- Only mail originating from one of those addresses would be accepted and
- would be copied locally, or relayed, to each subscribed address.
- It also should be possible to provide read-only mailing lists, where only
- specified mail accounts can post into.
-\begin_deeper 
-\layout Itemize
-
-
-\emph on 
-Design for this feature not yet complete.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-Abstract\SpecialChar ~
-authentication\SpecialChar ~
-and\SpecialChar ~
-storage\SpecialChar ~
-modules: When the data layout design is
- complete, I intend to write a C library of various functions which will
- be required by all 
-\series bold 
-mmmail
-\series default 
- daemons to manage mail.
- An underlaying lower level library should also be implemented, and would
- internally be used by the former library, via a structure of function pointers
- or other method.
- This will allow to abstract storage and authentication code to use for
- instance (MySQL, pgsql, file, db4, etc).
-\layout Section
-\pagebreak_top 
-Database tables design
-\layout Standard
-
-
-\begin_inset Graphics FormatVersion 1
-       filename /home/mmondor/mmmail/mmmail-tables.eps
-       display default
-       size_type 1
-       width 8.5in
-       keepAspectRatio
-       rotate
-       rotateAngle 90
-       rotateOrigin leftBaseline
-       lyxsize_type 1
-       lyxwidth 7in
-
-\end_inset 
-
-
-\layout Author
-\pagebreak_bottom 
-Figure 1 - Database tables design
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-admin
-\emph default 
- The description of all allowed remote administrators, with their permissions.
- These permissions are described as follows:
-\begin_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-modify_admin
-\emph default 
- Administrator is allowed to create, delete and manage list of administrators
- for assigned domains.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-modify_domain
-\emph default 
- Permission to create, delete and manage domains.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-modify_alias
-\emph default 
- Right to add and delete aliases for assigned domains.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-modify_nofrom
-\emph default 
- Permission to add and delete entries of allowed addresses/hosts which may
- use empty 
-\series bold 
-FROM
-\series default 
- commands via SMTP.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-modify_relayfrom
-\emph default 
- Privilege to add and delete permanent patterns of hosts and address masks
- to accept relaying from via SMTP.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-modify_user
-\emph default 
- Access to create and delete users within the assigned domains, which of
- course may each have mailboxes.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-modify_box
-\emph default 
- Adminisrator may create, delete and manage mailboxes of users within the
- allowed domains.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-modify_list
-\emph default 
- Administrator can create and delete addresses subscribed to mailing lists
- within assigned domains.
-\layout Standard
-
-It is important that the code makes sure that the login handle be unique
- when inserting a new entry in this table.
- Of course, an administrator who can create administrators can only lower
- levels of their own administrators; They thus cannot change a disabled
- permission on themselves or on their administrators.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-domain
-\emph default 
- This table contains one entry per known domain.
- Most delegated administration tasks will be performed on objects, all tied
- to specific domains.
- Tied to domains are the 
-\emph on 
-domain_admin
-\emph default 
-, 
-\emph on 
-alias
-\emph default 
-, 
-\emph on 
-nofrom
-\emph default 
-, 
-\emph on 
-relayfrom
-\emph default 
-, 
-\emph on 
-user
-\emph default 
-, 
-\emph on 
-box
-\emph default 
- and 
-\emph on 
-list
-\emph default 
- tables.
- The domain name is important, and will not be found anywhere else within
- the tables.
- It is important that the code makes sure that the domain name does not
- already exist when inserting a new domain.
- The 
-\emph on 
-lists
-\emph default 
- boolean field disables checking for mailing lists for this domain if FALSE,
- thus disabling all mailing lists temporarily for it, if any, and making
-\emph on 
-mmmail-smtpd
-\emph default 
- faster.
-\begin_deeper 
-\layout Itemize
-
-
-\emph on 
-Add other domain-specific permissions and limits for boxes, users, lists,
- admins, relaying.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-domain_admin
-\emph default 
- This table specifies which domains are linked to which administrators.
- Several administrators may be assigned to a domain, and several domains
- can be handled by an administrator.
- Of course the administrator permissions should be taken into account.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-alias
-\emph default 
- This holds entries for patterns matching a mailbox name which should be
- remapped to specific mailboxes.
- These only operate on the username part of email addresses, as they are
- domain-specific.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-nofrom
-\emph default 
- Each domain can also be assigned a list of hostname patterns or address
- masks which are allowed to use empty 
-\series bold 
-SMTP FROM
-\series default 
- commands such as 
-\series bold 
-FROM:<>
-\series default 
-.
- This table is global rather than tied to specific domains, and only special
- administrators should have access to modify it.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-relayfrom
-\emph default 
- Each domain are now assigned a list of client hostnames or addresses which
- should be automatically accepted to relay mail for.
- The expires field allows to implement the 
-\emph on 
-POP3-SMTP
-\emph default 
- and 
-\emph on 
-IMAP-SMTP
-\emph default 
- methods which could automatically setup an entry to allow relaying for
- a length of time for hosts which successfully authenticated through POP3
- or IMAP protocols first.
- Therefore, this table holds both permanent relay pattern matching entries,
- and temporary ones, matching specific addresses, which can expire.
- expires should be 0 for permanent entries.
-\begin_deeper 
-\layout Standard
-
-Like for 
-\emph on 
-nofrom
-\emph default 
-, only special administrators are allowed to modify the permanent entries
- of this table.
- They are global rather than on per-domain basis.
- The temporary expiring entries are automatically managed internally, while
- the permanent ones can be modified by an administrator with necessary permissio
-ns.
-\layout Itemize
-
-
-\emph on 
-It would be trivial to have the temporary expiring entries into a memory
- cache only, rather than in a table.
- For performance considerations this could be done.
- At least the design shows how it is possible to achieve by future 
-\series bold 
-mmmail
-\series default 
- version 2.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-box
-\emph default 
- Describes each mailbox, tied to their user and domain.
- Each box comports the quota limits with their current counters.
- It is important to make sure that the address field remain unique for the
- current domain when adding new boxes.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-list
-\emph default 
- Similarly to 
-\emph on 
-box
-\emph default 
-, specifies each mailing list for a domain.
- If mailing lists are enabled for a domain (
-\emph on 
-lists
-\emph default 
- field is TRUE in 
-\emph on 
-domain
-\emph default 
- table) this table is verified for a match by 
-\emph on 
-mmmail-smtpd
-\emph default 
- when receiving a message, before the box table be verified for potential
- matching.
- The 
-\emph on 
-from
-\emph default 
- field specifies which 
-\series bold 
-FROM
-\series default 
- address should be used when relaying the message to the subscribers.
- It is important that the code makes sure that it does not already exist
- when inserting a new list address for a domain.
-\begin_deeper 
-\layout Itemize
-
-
-\emph on 
-Several other list configuration fields may need to be added here.
- Possibly also a list of users which should not be allowed to subscribe,
- or rather a list of patterns which should match to choose which subscriber
- hosts to accept, etc.
- Also think of a control system on who is allowed to post.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-subscriber
-\emph default 
- This table specifies all subscribed addresses for a mailing list.
- These are verified by mmmail-listd before accepting the message for the
- list, to make sure that only subscribers can post.
- The accepted message is then dispatched to each subscriber, relayed if
- necessary (if relaying is allowed of course).
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-header
-\emph default 
- A header entry represents a message.
- As the message body can be shared accross multiple instances of the same
- messages in the various mailboxes, only the header is actually copied (See
-\emph on 
-body
-\emph default 
- table for more information).
- To this header are either linking, with mutual exclusion, an entry from
- the 
-\emph on 
-filterqueue
-\emph default 
-, 
-\emph on 
-boxqueue
-\emph default 
-, 
-\emph on 
-listqueue
-\emph default 
- or 
-\emph on 
-relayqueue
-\emph default 
-.
-\begin_deeper 
-\layout Standard
-
-When a header is deleted, it is important to decrease and verify the 
-\emph on 
-refcount
-\emph default 
- field of the corresponding 
-\emph on 
-body
-\emph default 
- table entry it links to, and to delete that body message entry when the
- counter reaches zero.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-body
-\emph default 
- This table contains all message bodies, to which are linking one or more
-\emph on 
-header
-\emph default 
- table entries.
- We maintain a 
-\emph on 
-refcount
-\emph default 
- field which permits to know when this entry is no longer referenced and
- may be deleted.
- This design permits to reduce the frequency of database operations on very
- large elements, and also to greatly optimize the operations and storage
- space requirements on mailing lists where subscribers consist of mailboxes
- we are providing.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-filterqueue
-\emph default 
- This table is only used if 
-\emph on 
-mmmail-filterd
-\emph default 
- runs and mail filtering options have been enabled.
- It allows to process all incomming mail which 
-\emph on 
-mmmail-smtpd
-\emph default 
- receives through sanity checking scripts before it gets dispatched into
- any other queues.
- The 
-\emph on 
-destination
-\emph default 
- field permits to know in which queue the message should be moved after
- passing the filter successfully, if it does.
- It also allows application-specific filters to be set by the system administrat
-or; A different filtering operation may be wanted for mail which has to
- be relayed than for mail which should be processed for a mailing list,
- etc.
-\begin_deeper 
-\layout Standard
-
-If mail filtering is disabled, 
-\emph on 
-mmmail-smtpd
-\emph default 
- moves the message immediately in the queue it belongs to, rather than letting
-\emph on 
-mmmail-filterd
-\emph default 
- do it asynchroneously.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-boxqueue
-\emph default 
- All ready messages into all local mailboxes have an entry in this table.
- These are ready to be accessed via 
-\emph on 
-mmmail-pop3d
-\emph default 
- and 
-\emph on 
-mmmail-imapd
-\emph default 
- services.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-listqueue
-\emph default 
- Mail which has been received for an address corresponding to a mailing
- list replicator is stored into this queue for processing by the 
-\emph on 
-mmmail-listd
-\emph default 
- service.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-relayqueue
-\emph default 
- All mail which should be relayed out (for both mailing list messages to
- non-local mailboxes and normal relaying) is stored in this queue, for processin
-g by the 
-\emph on 
-mmmail-relayd
-\emph default 
- service.
-\layout Section
-
-Server processes
-\layout Standard
-
-Here now consists of a list of the planned server processes, and their intended
- behavior.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-mmmail-smtpd
-\emph default 
- The standard SMTP server, now called 
-\emph on 
-mmsmtpd
-\emph default 
-, which accepts mail from SMTP clients, performing flood protection and
- various sanity checking, and dispatching new mail into the 
-\emph on 
-filterqueue
-\emph default 
-, 
-\emph on 
-listqueue
-\emph default 
-, 
-\emph on 
-boxqueue
-\emph default 
- or 
-\emph on 
-relayqueue
-\emph default 
-.
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-mmmail-filterd
-\emph default 
- Processes the 
-\emph on 
-filterqueue
-\emph default 
- entries, performs wanted sanity checking on mail, and then either drop,
- or move those to the 
-\emph on 
-boxqueue
-\emph default 
-, 
-\emph on 
-listqueue
-\emph default 
- or 
-\emph on 
-relayqueue
-\emph default 
-.
- This process is optional as 
-\emph on 
-mmmail-smtpd
-\emph default 
- can direct messages in their respected queues immediately if filtering
- is disabled.
-\begin_deeper 
-\layout Itemize
-
-
-\emph on 
-It is still under investigation as to how known third-party filters designed
- for sendmail should be used by 
-\emph default 
-mmmail-filterd
-\emph on 
-.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-mmmail-listd
-\emph default 
- This process handles the 
-\emph on 
-listqueue
-\emph default 
- and makes sure that the originator address matches a subscribed address,
- to then fill the 
-\emph on 
-boxqueue
-\emph default 
- to deliver local mailoxes, or the 
-\emph on 
-relayqueue
-\emph default 
- to relay mail out to the subscribers.
-\begin_deeper 
-\layout Standard
-
-This server could also support and handle subscription and unsubscription
- requests, sending a confirmation email back with a code which it would
- expect back within a period of time to subscribe the new address.
-\layout Itemize
-
-
-\emph on 
-A new table should be created for the expected responses with expiration.
- Also should be taken into account limits for maximum number of subscribers,
- number of failed relayed mail to automatically unsubscribe an address,
- etc.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-mmmail-relayd
-\emph default 
- This server processes the 
-\emph on 
-relayqueue
-\emph default 
- and attempts to act as an SMTP client to send mail out to the SMTP servers
- pointed out by the MX record for the destination domain.
- An entry is deleted from the 
-\emph on 
-relayqueue
-\emph default 
- when it expires (too many retries or expired retry period), in which case
- reply mail could be bounced to the mail originator, or when mail has successful
-ly been relayed out.
-\begin_deeper 
-\layout Itemize
-
-
-\emph on 
-Some investigation should be done about how to effectively send mail out
- using more than an RCPT when possible (with decent limit) and to send to
- more than a single server at a time without slowing too much database access
- because of transactions.
- Moreover, perhaps that some MX address cacheing is desirable.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-mmmail-pop3d
-\emph default 
- The standard POP3 protocol client frontend, internally processing the 
-\emph on 
-boxqueue
-\emph default 
-.
-\begin_deeper 
-\layout Itemize
-
-
-\emph on 
-Support for APOP should be envisaged.
-\end_deeper 
-\layout List
-\labelwidthstring 00.00.0000
-
-
-\emph on 
-mmmail-imapd
-\emph default 
- The standard IMAP protocol client frontend, internally working on the 
-\emph on 
-boxqueue
-\emph default 
-.
-\the_end
diff --git a/mmsoftware/mmmail2/notes/mmmail-tables.dia b/mmsoftware/mmmail2/notes/mmmail-tables.dia
deleted file mode 100644 (file)
index 4469aea..0000000
Binary files a/mmsoftware/mmmail2/notes/mmmail-tables.dia and /dev/null differ
diff --git a/mmsoftware/mmpasswd/GNUmakefile b/mmsoftware/mmpasswd/GNUmakefile
deleted file mode 100644 (file)
index 5fbd7c3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-# $Id: GNUmakefile,v 1.2 2004/05/31 06:15:43 mmondor Exp $
-
-MMLIBS := $(addprefix ../mmlib/,mmstring.o)
-
-OBJS := mmpasswd.o
-
-CFLAGS += -Wall
-
-
-all: mmpasswd
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I../mmlib -o $@ $<
-
-mmpasswd: $(MMLIBS) $(OBJS)
-       cc -o $@ -lc -lcrypt $(OBJS) $(MMLIBS)
-
-install:
-       install -cs -o 0 -g 0 -m 550 mmpasswd /usr/local/sbin
-       install -c -o 0 -g 0 -m 444 mmpasswd.8 /usr/local/man/man8
-
-clean:
-       rm -f mmpasswd $(OBJS) $(MMLIBS)
diff --git a/mmsoftware/mmpasswd/Makefile b/mmsoftware/mmpasswd/Makefile
deleted file mode 100644 (file)
index ad414b4..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-# $Id: Makefile,v 1.3 2003/01/01 14:54:11 mmondor Exp $
-
-CC = gcc
-MAKE = make
-
-CFLAGS += -D_REENTRANT -Wall
-
-INCDIR = -I/usr/include -I/usr/pkg/include -I../mmlib
-LIBDIR = -L/lib -L/usr/lib -L/usr/pkg/lib
-
-LIBS = ../mmlib/libmmondor.a -lc -lcrypt
-
-OBJS = mmpasswd.o
-
-
-
-CCOBJ = $(CC) $(CFLAGS) -c $(INCDIR)
-
-
-
-
-mmpasswd: $(OBJS)
-       $(CC) $(CFLAGS) -o mmpasswd $(INCDIR) $(LIBDIR) $(OBJS) $(LIBS)
-
-
-
-
-clean:
-       -rm -f $(OBJS) mmpasswd
-
-
-
-
-mmpasswd.o:
-       $(CCOBJ) mmpasswd.c
-
diff --git a/mmsoftware/mmpasswd/make.sh b/mmsoftware/mmpasswd/make.sh
deleted file mode 100755 (executable)
index 4d25a62..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-# $Id: make.sh,v 1.1 2002/12/11 10:16:19 mmondor Exp $
-
-. ../mmlib/makefuncs.sh
-
-clean mmpasswd
-makebin mmpasswd
-instbin mmpasswd
diff --git a/mmsoftware/mmpasswd/makepart.sh b/mmsoftware/mmpasswd/makepart.sh
deleted file mode 100755 (executable)
index 1d296d4..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-# $Id: makepart.sh,v 1.3 2003/01/01 14:54:11 mmondor Exp $
-
-. ../mmlib/makedefs.sh
-
-OBJS='mmpasswd.o'
-BIN1='mmpasswd'
-
-if [ "$1" = "clean" ]; then
-       show $RM $OBJS $BIN1
-       exit 0
-fi
-
-INCDIR="-I../mmlib $STDINC"
-LIBDIR="$STDLIB"
-LIBS='../mmlib/libmmondor.a -lc -lcrypt'
-
-for obj in $OBJS; do
-       if [ ! -f $obj ]; then
-               src=`$ECHO $obj | $SED 's/\.o$/.c/'`
-               show $CC $CFLAGS -c $INCDIR $src
-       fi
-done
-
-show $CC $CFLAGS -o $BIN1 $INCDIR $LIBDIR $BIN1.o $LIBS
diff --git a/mmsoftware/mmpasswd/mmpasswd.8 b/mmsoftware/mmpasswd/mmpasswd.8
deleted file mode 100644 (file)
index 526cd73..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-.\" $Id: mmpasswd.8,v 1.4 2004/05/06 00:05:35 mmondor Exp $
-.\"
-.\" Copyright (C) 2002-2004, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd 22 Dec, 2002
-.Dt MMPASSWD 8
-.Os
-.Sh NAME
-.Nm mmpasswd
-.Nd password hash generation for
-.Xr mmmail 8
-and
-.Xr mmftpd 8
-and matching for related utilities
-.Sh SYNOPSIS
-.Nm mmpasswd
-.Ar 'password'
-.Op 'hash'
-.Sh DESCRIPTION
-In it's first form, with only
-.Ar password
-argument given,
-.Nm mmpasswd
-utility uses
-.Xr crypt 3
-to hash the provided password string using MD5, which should be enclosed
-in quotes if the password contains spaces. It then outputs a text form
-of the hash in a case-sensitive representation. This hash should be
-compatible with those of the current system.
-.Pp
-The resulting string is suitable for use in
-.Xr mmmail 8
-.Nm user
-MySQL table, or for
-.Xr mmftpd 8
-user database
-.Xr mmftpdpasswd 5
-file.
-.Pp
-The authentication of these daemons will be performed by performing the same
-conversions on the user supplied password, still using
-.Xr crypt 3 ,
-and then comparing the result with the database entry for that user,
-case-sensitively.
-.Pp
-The second invokation form of
-.Nm mmpasswd
-requires a second argument,
-.Ar hash ,
-which when provided will be used to evaluate matching of the supplied
-password with the supplied hash. This works for both traditional DES
-and recent MD5 implementations. When invoked this way,
-.Nm mmpasswd
-will output to standard output '0' for success (authentication successful)
-or '-1' for failiure. Similarly, the executable will return the same value
-as it's error code. This can be useful for the administrator and for scripts
-or various frontends.
-.Sh AUTHOR
-.Nm mmpasswd
-was written by Matthew Mondor
-.Sh SEE ALSO
-.Xr mmftpdpasswd 5 ,
-.Xr mmmail 8 ,
-.Xr crypt 3 .
-.Sh BUGS
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/mmpasswd/mmpasswd.c b/mmsoftware/mmpasswd/mmpasswd.c
deleted file mode 100644 (file)
index af96d8a..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/* $Id: mmpasswd.c,v 1.6 2004/05/06 00:05:35 mmondor Exp $ */
-
-/*
- * Copyright (C) 2002-2004, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <time.h>
-#include <stdio.h>
-#ifdef __GLIBC__
-#include <crypt.h>
-#endif
-
-#include <mmtypes.h>
-#include <mmstring.h>
-
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2002-2004\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmpasswd.c,v 1.6 2004/05/06 00:05:35 mmondor Exp $");
-
-
-
-
-/* The only reason we use structures here is for security considerations;
- * We wouldn't want the caller to supply smaller buffers than required and
- * cause buffer overflows. And the generated results have fixed number of
- * bytes, so let's not require the user to specify the length of his buffers,
- * it could be wrong anyways.
- *
- * XXX Using structures serves no purpose here, but they don't harm neither.
- * so I left this unchanged for mmpasswd.
- */
-
-struct salt_md5 {
-    /* Restrict salt to 6 characters since PHP crypt() seems to have this
-     * limit.
-     */
-    char salt[7];
-};
-
-struct hash_md5 {
-    char hash[35];
-};
-
-int main(int, char **);
-void seedrandom(void);
-void gensalt_md5(struct salt_md5 *);
-void genhash_md5(struct hash_md5 *, const char *);
-int test(const char *, const char *);
-
-
-
-
-int main(int argc, char **argv)
-{
-    if (argc == 2) {
-
-       struct hash_md5 hash_md5;
-
-       seedrandom();
-
-       genhash_md5(&hash_md5, argv[1]);
-       printf("%s\n", hash_md5.hash);
-
-       exit(0);
-
-    } else if (argc == 3) {
-
-       int res;
-
-       res = test(argv[1], argv[2]);
-       printf("%d\n", res);
-       exit(res);
-
-    } else printf("Usage: mmpasswd '<password>' ['hash']\n");
-
-    exit(-1);
-}
-
-
-void seedrandom(void)
-{
-    int fd;
-    unsigned long s;
-
-    if ((fd = open("/dev/urandom", O_RDONLY)) != -1) {
-       if (read(fd, &s, sizeof(unsigned long)) == sizeof(unsigned long))
-           srandom(s);
-       close(fd);
-    } else
-       /* Not really good, but better than nothing */
-       srandom(time(NULL));
-}
-
-
-void gensalt_md5(struct salt_md5 *salt)
-{
-    int i, t = sizeof(salt->salt) - 1;
-    static const char table[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\
-abcdefghijklmnopqrstuvwxyz";
-
-    for (i = 0; i < t; i++)
-       salt->salt[i] = table[random() % (sizeof(table) - 1)];
-    salt->salt[t] = '\0';
-}
-
-
-void genhash_md5(struct hash_md5 *hash, const char *pass)
-{
-    struct salt_md5 salt;
-    char setting[14], *ptr;
-    int t = sizeof(hash->hash) - 1;
-
-    gensalt_md5(&salt);
-    snprintf(setting, 13, "$1$%s$", salt.salt);
-    if ((ptr = crypt(pass, setting)) != NULL) {
-       mm_memcpy(hash->hash, ptr, t);
-       hash->hash[t] = '\0';
-    } else hash->hash[0] = '\0';
-}
-
-
-int test(const char *passwd, const char *hash)
-{
-    char *ptr;
-
-    if ((ptr = crypt(passwd, hash)) != NULL) {
-       if (mm_strcmp(ptr, hash) == 0)
-           return (0);
-    }
-
-    return (-1);
-}
diff --git a/mmsoftware/mmsendmail/GNUmakefile b/mmsoftware/mmsendmail/GNUmakefile
deleted file mode 100644 (file)
index 23072cb..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# $Id: GNUmakefile,v 1.2 2004/06/02 01:08:26 mmondor Exp $
-
-MMLIBS := $(addprefix ../mmlib/,mmfd.o mmstring.o)
-
-OBJS := mmsendmail.o
-
-CFLAGS += -Wall
-
-
-all: mmsendmail
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I../mmlib -o $@ $<
-
-mmsendmail: $(MMLIBS) $(OBJS)
-       cc -o $@ -lc $(OBJS) $(MMLIBS)
-
-install:
-       install -cs -o 0 -g 0 -m 550 mmsendmail /usr/local/libexec
-
-clean:
-       rm -f mmsendmail $(OBJS) $(MMLIBS)
diff --git a/mmsoftware/mmsendmail/Makefile b/mmsoftware/mmsendmail/Makefile
deleted file mode 100644 (file)
index 7fe3372..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# $Id: Makefile,v 1.3 2003/10/13 11:20:04 mmondor Exp $
-
-CC = gcc
-MAKE = make
-
-CFLAGS += -Wall -DDEBUG
-
-INCDIR = -I../mmlib -I/usr/include -I/usr/pkg/include -I.
-LIBDIR = -L/usr/local/lib -L/usr/lib -L/lib -L/usr/pkg/lib
-
-LIBS = ../mmlib/libmmondor.a -lc
-
-OBJS = mmsendmail.o
-
-
-
-CCOBJ = $(CC) $(CFLAGS) -c $(INCDIR)
-
-
-
-
-mmsendmail: $(OBJS)
-       $(CC) $(CFLAGS) -o mmsendmail $(INCDIR) $(LIBDIR) $(OBJS) $(LIBS)
-
-
-
-
-clean:
-       -rm -f $(OBJS) mmsendmail
-
-
-mmsendmail.o:
-       $(CCOBJ) mmsendmail.c
-
diff --git a/mmsoftware/mmsendmail/mmsendmail.c b/mmsoftware/mmsendmail/mmsendmail.c
deleted file mode 100644 (file)
index 1344639..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/* $Id: mmsendmail.c,v 1.11 2004/11/09 11:53:16 mmondor Exp $ */
-
-/*
- * Copyright (C) 2000-2004, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* mmsendmail.c by Matthew Mondor
- * 
- * USAGE: mmsendmail <smtphost> <port> <fromaddr> <authcompname|none>
- * -- <toaddresses...>
- * 
- * Useful to replace MTAs for use by Mutt and Pine.
- * Replace "sendmail -oem -oi" command by:
- * "mmsendmail smtp.somehost.net 25 my@address.net optionalauthname|none"
- * 
- * Another great use for this is that it can use any port we want, it thus
- * could connect to a forwarded port on localhost, say 2525 which could
- * be tunneled through ssh to another SMTP server.
- *
- */
-
-#include <sys/types.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <syslog.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <mmtypes.h>
-#include <mmfd.h>
-#include <mmstring.h>
-
-
-
-int            main(int, char **);
-static int     result(void);
-static bool    eintr(void);
-static int     validate(char *, ssize_t *, int *, void *);
-static void    sighandler(int);
-
-
-
-static fdbuf   *fdb;
-static bool    endheader, toheader, fromheader;
-static char    *fromaddr;
-
-
-
-int
-main(int argc, char **argv)
-{
-    struct sockaddr_in server;
-    struct hostent     *he;
-    struct in_addr     *ip;
-    fdbuf              *fdbi;
-    int                        msgsock, res, ret, cnt;
-    char               *hostname = NULL, *authcompname = NULL;
-    bool               authok = FALSE, rcptok = FALSE;
-    unsigned short     port = 25;
-    fdfuncs            fdf = {
-       malloc,
-       free,
-       poll,
-       read,
-       write,
-       sleep,
-       usleep,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       eintr
-    };
-    struct fdbrb_buffer        *fdbrb;
-    struct sigaction   act;
-
-    fdbi = fdb = NULL;
-    msgsock = -1;
-    fdbrb = NULL;
-    ret = EXIT_FAILURE;
-    endheader = toheader = fromheader = FALSE;
-    fromaddr = NULL;
-
-    if (argc > 6) {
-       hostname = argv[1];
-       port = (unsigned short)atoi(argv[2]);
-       fromaddr = argv[3];
-       authcompname = argv[4];
-    } else {
-       syslog(LOG_NOTICE, "Usage");
-       fprintf(stderr, "Usage: mmsendmail <hostname> <port> <fromaddr> \
-<helohost|none> -- <rcptaddr> [<rcptaddr> ...]\n");
-       goto end;
-    }
-
-    /* Setup signal handler */
-    act.sa_handler = sighandler;
-    act.sa_flags = SA_NOCLDWAIT;
-    sigemptyset(&act.sa_mask);
-    sigaction(SIGTERM, &act, NULL);
-    sigaction(SIGPIPE, &act, NULL);
-    sigaction(SIGSEGV, &act, NULL);
-
-    /* We want to immediately read any stdin input until EOF */
-    if ((fdbi = fdbopen(&fdf, NULL, fileno(stdin), 4096, 4096, 0, 0, 60000,
-                   60000, FALSE)) == NULL) {
-       fprintf(stderr, "* fdbopen(stdin)\n");
-       syslog(LOG_NOTICE, "fdbopen(stdin)");
-       goto end;
-    }
-    if ((res = fdbreadbuf(&fdbrb, fdbi, 32768, 1024, 0, 0, validate, NULL,
-                   FALSE)) != FDBRB_EOF) {
-       fprintf(stderr, "* fdbreadbuf()\n");
-       syslog(LOG_NOTICE, "fdbreadbuf()");
-       goto end;
-    }
-
-    /* Obtain IP address of supplied hostname if not already an address */
-    if ((he = gethostbyname(hostname)))
-       ip = (struct in_addr *)he->h_addr_list[0];
-    else {
-       syslog(LOG_NOTICE, "Cannot resolve hostname");
-       fprintf(stderr, "* Cannot resolve hostname");
-       goto end;
-    }
-
-    /* Create TCP/IP communications socket */
-    if ((msgsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
-       syslog(LOG_NOTICE, "Cannot create socket");
-       fprintf(stderr, "* Cannot create socket");
-       goto end;
-    }
-
-    /* Setup our structure to connect to server */
-    mm_memclr(&server, sizeof(struct sockaddr_in));
-    server.sin_family = AF_INET;
-    server.sin_addr.s_addr = ip->s_addr;
-    server.sin_port = htons(port);
-
-    /* Attempt to connect to host */
-    if ((connect(msgsock, (struct sockaddr *)&server, sizeof(server)))
-           != 0) {
-       fprintf(stderr, "* Cannot connect to server");
-       syslog(LOG_NOTICE, "Cannot connect to server");
-       goto end;
-    }
-
-    if ((fdb = fdbopen(&fdf, NULL, msgsock, 4096, 4096, 0, 0, 60000,
-                   60000, FALSE)) == NULL) {
-       fprintf(stderr, "* fdbopen(sock)");
-       syslog(LOG_NOTICE, "fdbopen(sock)");
-       goto end;
-    }
-
-    if (result() == 220) {
-
-       /* Authenticate if wanted */
-       if (mm_strcmp(authcompname, "none") != 0) {
-           fdbprintf(fdb, "HELO %s\r\n", authcompname);
-           fdbflushw(fdb);
-           if (result() == 250)
-               authok = TRUE;
-           else
-               authok = FALSE;
-       } else
-           authok = TRUE;
-
-       if (authok) {
-           /* Tell server who we are sending from */
-           fdbprintf(fdb, "MAIL FROM:<%s>\r\n", fromaddr);
-           fdbflushw(fdb);
-           if (result() == 250) {
-
-               /* Tell server all addresses to send this message to;
-                * those were provided on commandline by Mutt/Pine
-                */
-               rcptok = TRUE;
-               for (cnt = 6; cnt < argc; cnt++) {
-                   fdbprintf(fdb, "RCPT TO:<%s>\r\n", argv[cnt]);
-                   fdbflushw(fdb);
-                   if (result() != 250) {
-                       syslog(LOG_NOTICE, "RCPT TO failed");
-                       fprintf(stderr, " * RCPT TO failed\n");
-                       rcptok = FALSE;
-                       break;
-                   }
-               }
-
-               if (rcptok) {
-                   fdbrwrite(fdb, "DATA\r\n", 6);
-                   if (result() == 354) {
-                       /* Send our message data */
-                       if (fdbrwrite(fdb, fdbrb->array, fdbrb->current) !=
-                               fdbrb->current ||
-                               fdbrwrite(fdb, ".\r\n", 3) != 3) {
-                           syslog(LOG_NOTICE, "Failed sending message data");
-                           fprintf(stderr, " * Message send failed\n");
-                           goto end;
-                       }
-
-                       /* Was message accepted? */
-                       if (result() == 250)
-                           ret = EXIT_SUCCESS;
-                       else {
-                           syslog(LOG_NOTICE, "Message refused by server");
-                           fprintf(stderr, " * Message refused by server\n");
-                       }
-                   }
-               }
-
-           } else {
-               syslog(LOG_NOTICE, "MAIL FROM failed");
-               fprintf(stderr, " * MAIL FROM failed");
-           }
-       } else {
-           syslog(LOG_NOTICE, "HELO failed");
-           fprintf(stderr, " * HELO failed\n");
-       }
-
-       /* Disconnect from server */
-       fdbrwrite(fdb, "QUIT\r\n", 6);
-
-    } else {
-       syslog(LOG_NOTICE, "Unexpected server welcome message");
-       fprintf(stderr, " * Unexpected server welcome message\n");
-    }
-
-end:
-    fdbfreebuf(&fdbrb);
-    if (fdbi != NULL)
-       fdbclose(fdbi);
-    if (fdb != NULL)
-       fdbclose(fdb);
-    if (msgsock != -1)
-       close(msgsock);
-
-    return ret;
-}
-
-
-static int
-result(void)
-{
-    int                res = -1;
-    char       buffer[1024];
-
-    if ((fdbgets(fdb, buffer, 1023, TRUE)) > 0)
-       res = atoi(buffer);
-
-    return res;
-}
-
-
-static bool
-eintr(void)
-{
-
-    if (errno == EINTR)
-       return TRUE;
-
-    return FALSE;
-}
-
-
-/* ARGSUSED */
-static int
-validate(char *line, ssize_t *len, int *res, void *udata)
-{
-
-    if (!endheader) {
-       char    *ptr;
-
-       if (len == 0 || (ptr = mm_strchr(line, ':')) == NULL)
-           goto eh;
-       if (ptr[1] != ' ')
-           goto eh;
-       /* Verify if we get mandatory header lines */
-       if (mm_strncmp(line, "To: ", 4) == 0)
-           toheader = TRUE;
-       if (mm_strncmp(line, "From: ", 6) == 0)
-           fromheader = TRUE;
-    } else {
-       /* Convert '.' to '..', we must be the one sending the final dot. */
-       if (line[0] == '.' && line[1] == '\0') {
-           line[1] = '.';
-           line[2] = '\0';
-           (*len)++;
-       }
-    }
-
-    return FDBRB_OK;
-
-eh:
-    {
-       char    tline[1024];
-
-       endheader = TRUE;
-
-       /* Add mendatory headers if necessary */
-       *tline = '\0';
-       if (!fromheader)
-           (void) snprintf(tline, 1023, "From: %s",
-                           fromaddr);
-       if (!toheader)
-           (void) snprintf(tline, 1023, "%s\r\nTo: undisclosed-recipients:;",
-                           tline);
-       if (*tline != '\0') {
-           if (*len != 0) {
-               /* Insert header before message line */
-               (void) snprintf(tline, 1023, "%s\r\n\r\n%s\r\n", tline, line);
-               *len = mm_strncpy(line, tline, 1023);
-           } else {
-               /* Replace current empty line by header */
-               (void) snprintf(line, 1023, "%s\r\n", tline);
-               *len = mm_strlen(line);
-           }
-       }
-    }
-
-    return FDBRB_OK;
-}
-
-
-static void
-sighandler(int sig)
-{
-    char       *s = NULL;
-
-    switch (sig) {
-    case SIGSEGV:
-       s = "SIGSEGV (segmentation fault)";
-       break;
-    case SIGPIPE:
-       s = "SIGPIPE (server dropped connection)";
-       break;
-    case SIGTERM:
-       s = "SIGTERM (we were killed)";
-       break;
-    default:
-       s = "We received a spurious signal!";
-    }
-
-    syslog(LOG_NOTICE, "SIGNAL: %s", s);
-    fprintf(stderr, " * Received signal: %s\n", s);
-    exit(EXIT_FAILURE);
-}
diff --git a/mmsoftware/mmspawnd/GNUmakefile b/mmsoftware/mmspawnd/GNUmakefile
deleted file mode 100644 (file)
index 05bf763..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# $Id: GNUmakefile,v 1.7 2003/11/12 05:37:18 mmondor Exp $
-
-MMLIBS := $(addprefix ../mmlib/,mmpool.o mmlog.o mmreadcfg.o mmstring.o \
-mmhash.o mmalarm.o mmheap.o mmlimitrate.o)
-OBJS := mmspawnd.o
-CFLAGS += -Wall -DDEBUG
-
-all: mmspawnd
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I../mmlib -o $@ $<
-
-mmspawnd: $(MMLIBS) $(OBJS)
-       cc -o $@ $(OBJS) -lc $(MMLIBS)
-
-install: all
-       install -cs -o 0 -g 0 -m 500 mmspawnd /usr/local/sbin
-       install -c -o 0 -g 0 -m 444 mmspawnd.conf.5 /usr/local/man/man5
-       install -c -o 0 -g 0 -m 444 mmspawnd.8 /usr/local/man/man8
-
-clean:
-       rm -f mmspawnd $(OBJS) $(MMLIBS)
diff --git a/mmsoftware/mmspawnd/mmspawnd.8 b/mmsoftware/mmspawnd/mmspawnd.8
deleted file mode 100644 (file)
index 84322a5..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-.\" $Id: mmspawnd.8,v 1.7 2003/11/10 00:52:11 mmondor Exp $
-.\"
-.\" Copyright (C) 2003, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\" 5. Redistribution of source code may not be released under the terms of
-.\"    any GNU Public License derivate.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd October 28, 2003
-.Dt MMSPAWND 8
-.Os mmsoftware
-.Sh NAME
-.Nm mmspawnd
-.Nd
-.Xr inetd 8
-alternative for better security
-.Sh SYNOPSIS
-.Nm mmspawnd Op Ar config_file
-.Sh DESCRIPTION
-.Nm
-is a useful replacement for
-.Xr inetd 8
-when security is a concern. It only allows to serve one service per running
-instance, but a different configuration file can be provided for each service
-to run several ones as required. It supports connection number and rate limits
-on a global and per-address basis,
-.Xr chroot 2
-and
-.Xr setrlimit 2 . It will only
-.Xr bind 2
-to specified addresses/interfaces to listen for connections.
-It also ensures to drop privileges definitely before starting operation, using
-.Xr setgid 2 ,
-.Xr setuid 2
-and
-.Xr setgroups 2 .
-.Pp
-Further, it comports a safe
-.Xr execve 2
-wrapper which ensures to not pass unexpected arguments or environmental
-variables, as well as to only execute ELF binaries which are owned by the
-superuser and non-writable. No globbing whatsoever is performed by it,
-and it only allows an absolute path to be provided to the application to
-launch. It will not allow execution of files with the setuid or setgid
-bits set.
-.Pp
-All connections are logged via the specified facility using
-.Xr syslog 3 ,
-as well as the exit code of the application when closing the connection with
-the client. Any security issue encoutered by the
-.Xr execve 2
-wrapper is also logged.
-.Pp
-It's default configuration makes it harmless but useless. See the
-.Xr mmspawnd.conf 5
-manual page for configuration file description.
-.Pp
-A good usage for
-.Xr mmspawnd 8
-is for instance to run a CVS pserver in safe conditions. It then can be
-restrited to the specified root directory, and access the files with read-only
-access under an unprivileged user. If used for this purpose, also look at
-the
-.Xr mmanoncvs 8
-manual page.
-.Pp
-Another interesting feature is being able to specify if the currently running
-clients should be interrupted or not if the
-.Nm
-server is to be stopped or restarted. In the case of a CVS checkout for
-instance, if
-.Nm KILL_CHILDREN
-configuration option is FALSE, the operation will continue until it finishes
-normally, even in the event of a server configuration change or restart.
-.Pp
-For additional security, only the superuser is allowed to launch
-.Nm ,
-unless compiled with the
-.Nm -DNODROPPRIVS
-option, in which case it could be used by a nonprivileged user to bind
-a service to a high port, and server refuse to be launched by root.
-Other users attempting to launch the service will cause a line to be logged,
-telling which user ID attempted the launch.
-.Pp
-When launched successfully, a status line is logged telling under which 
-user ID it runs, which port it listens to and on which addresses/interfaces,
-as well as the configuration file location and service command.
-.Pp
-Note that this system redirects the stderr stream (filedescriptor 2) of
-the command launched to serve the clients to the "/dev/null" device, so that
-errors output from it be not disclosed to the remote user.
-.Pp
-Another optional interesting feature which it offers is the possibility
-to use advisory locking on a special control file to synchronize the service
-with another program. The lock is acquired in exclusive mode by
-.Nm
-when at least one connection exists being served. It is released when no
-more connections remain. This way, another program can rely on the fact that
-noone is using the service if it can obtain the lock. As long as the other
-application holds the lock, the service will refuse new connections. Normal
-service resumes immediately as the lock is released by the third party
-application. Of course, it is important to properly configure the permissions
-on that lock file, if the feature is enabled.
-.Pp
-Eventual support for bandwidth shaping/throttling and network inactivity
-timeout limits are planned. However, as those will require a redesign and
-rewrite of
-.Nm ,
-all we support for now is total maximum timeout for execution of the supplied
-service command. This is still better than
-.Xr inetd 8
-behavior, however.
-.Sh FILES
-.Bl -tag -width indent -offset indent
-.It Pa /usr/local/sbin/mmspawnd
-The actual server binary
-.It Pa /usr/local/etc/mmspawnd.conf
-The default configuration file to read
-.El
-.Sh AUTHOR
-.Nm
-was written by Matthew Mondor, and is
-Copyright (c) 2003, Matthew Mondor, All Rights Reserved.
-.Sh SEE ALSO
-.Xr mmspawnd.conf 5 ,
-.Xr bind 2 ,
-.Xr chroot 2 ,
-.Xr setrlimit 2 ,
-.Xr setuid 2 ,
-.Xr setgid 2 ,
-.Xr setgroups 2 ,
-.Xr mmanoncvs 8 ,
-.Xr inetd 8 .
-.Sh BUGS
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/mmspawnd/mmspawnd.c b/mmsoftware/mmspawnd/mmspawnd.c
deleted file mode 100644 (file)
index 622b3ce..0000000
+++ /dev/null
@@ -1,1709 +0,0 @@
-/* $Id: mmspawnd.c,v 1.26 2004/09/29 00:43:41 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * An inetd-like network server, but which only listens to one port and
- * launches one command. It however performs alot more sanity checking,
- * and has support for chroot(2), custom limits, and setrlimit(2) ones
- * (for the children only, since we handle our own limits checking).
- * To use it for several services, a separate configuration file should
- * be provided for each.
- */
-
-/* TODO:
- * - It would be nice to have all I/O of all client processes be tunnelled
- *   through a bandwidth shaper process (which could then use mmfd(3)).
- *   However, this is not an immediate concern.
- * - Although we cannot monitor if a child process is idle properly using
- *   the current method, it would be nice to have a maximum time to live
- *   parameter in seconds.
- * - The first and second problems could both be solved if we implemented
- *   a popen()-like system instead of having the children serve directly
- *   the socket. We either could have another dedicated process handle the
- *   I/O of many ongoing connections, or to have the main system use it
- *   while still verifying for connection events. Doing this would both
- *   allow custom bandwidth shaping, as well as real network inactivity
- *   monitoring. If using such a method, it would probably be nice to use
- *   a library like libevent or libio which could take adventage of features
- *   like kqueue and epoll where available. Using poll(2) wouldn't be too
- *   bad however...
- * - Think properly. We have a recursion prevention lock, which should use
- *   a lock path outside of the chroot(2) if any. We have the ALOCK_PATH,
- *   which can also be outside the chroot(2), since only the parent locks it.
- *   However, there is the LOCK_PATH which should be inside the chroot(2) if
- *   any, because both the parent, cache manager and children processes are
- *   locking it. These files also need to be readable by the user or group
- *   under which mmspawnd(8) runs, so that shlocks_reopen() works. Hmm these
- *   are not used in the children processes however, only by the cache manager
- *   process after launch... Either we have chroot(2) called in each, in which
- *   case the files can be anywhere on the filesystem, or we cause those lock
- *   files to be created after chroot(2). Also, because we drop privileges
- *   after this, both can write and open the locks fine permission-wise.
- *   So plz hlp wut 2 doo 2 nut teh errer kthx!!11111 u teh their!?1//
- *   Argh!!! children processes call client_resolve()! Hence they also need
- *   to reopen lock file(s)... So LOCK_PATH HAS to be within the chroot(2),
- *   and chroot(2) needs to be called before calling shlocks_init()!
- * - Fix client_resolve() so that getnameinfo(3) can be called concurrently.
- * - Update man page about lock paths requirements etc!
- */
-
-
-
-#include <sys/types.h>
-#include <sys/file.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/poll.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <time.h>
-#include <syslog.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>    /* strerror(3) */
-
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-#include <sys/socket.h> 
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-
-/* For more information about these, see the manual pages in mmlib/ */
-#include <mmtypes.h>
-#include <mmstring.h>
-#include <mmreadcfg.h>
-#include <mmlist.h>
-#include <mmpool.h>
-#include <mmhash.h>
-#include <mmlog.h>
-#include <mmheap.h>
-#include <mmlimitrate.h>
-#include <mmalarm.h>
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2003\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmspawnd.c,v 1.26 2004/09/29 00:43:41 mmondor Exp $");
-
-
-
-/* DEFINITIONS */
-
-#define DAEMON_NAME            "mmspawnd"
-#define DAEMON_VERSION         "0.0.2/mmondor"
-
-struct configuration {
-    char CHROOT_DIR[256], LOCKS_PATH[256], LOCKS_USER[32], LOCKS_GROUP[32],
-       LOCKS_MODE[4], PID_PATH[256], USER[32], GROUPS[256], LOG_FACILITY[32],
-       LISTEN_ADDRESSES[1024], COMMAND[256], ALOCK_PATH[256], ALOCK_USER[32],
-       ALOCK_GROUP[32], ALOCK_MODE[4], PROCTITLE[64], STDERR_FILE[256];
-    long LISTEN_PORT, MAX_CONNECTIONS, MAX_ADDRESSES, MAX_PER_ADDRESS,
-       CONNECTION_RATE, CONNECTION_PERIOD, MAX_ARGUMENTS, COMMAND_TIMEOUT,
-       LIMIT_CORE, LIMIT_CPU, LIMIT_DATA, LIMIT_FSIZE, LIMIT_MEMLOCK,
-       LIMIT_NOFILE, LIMIT_NPROC, LIMIT_RSS, LIMIT_STACK;
-    bool RESOLVE_ADDRESSES, KILL_CHILDREN, RLIMITS;
-};
-
-/* Necessary synchronization locks for shared memory access */
-enum shlocks {
-    SHLOCK_IPADDR = 0,
-    SHLOCK_MAX
-};
-
-/* Base to shared memory, significant both in the parent and children
- * processes. The associated synchronization lock is commented.
- */
-struct shmem_data {
-    /* Locked with SHLOCK_IPADDR */
-    pool_t ipaddr_pool;
-    hashtable_t ipaddr_table;
-};
-
-/* Base to client-specific data, only significant for each children process */
-struct client_data {
-    struct ipaddr_node *ipn;
-    const char *ipaddr;
-    struct sockaddr saddr;
-};
-
-/* And server-specific data */
-struct server_data {
-    int runlock, alock, current_connections;
-    pool_t pid_pool;
-    hashtable_t pid_table;
-    timerctx_t timers;
-    char *line, *command, **argv;
-};
-
-/* Defines an interface to listen to */
-struct iface {
-    char address[16];          /* Server address string or '\0' */
-    int sock;                  /* Bound socket (or -1) */
-    struct sockaddr_in saddr;  /* Address to bind(2) to */
-};
-
-/* Used for the hostname cache and per-address connection rate limiting */
-struct ipaddr_node {
-    hashnode_t node;
-    struct limitrate lr;
-    struct sockaddr address;   /* Key */
-    long connections;
-    char hostname[64];
-};
-
-/* Used to efficiently link a child pid_t to an ipaddr_node structure pointer,
- * so that we may easily decrease the total connections counter for that
- * address in our SIGCHLD handler.
- */
-struct pid_node {
-    hashnode_t node;
-    pid_t pid;                 /* Key */
-    timerid_t tid;
-    struct ipaddr_node *ipn;
-};
-
-/* Used to store shared context between ipddr_expire_process() and it's
- * iterator function
- */
-struct ipaddr_expire_process_iterator_udata {
-    time_t current, soonest;
-};
-
-/* Useful macro to cleanup code later */
-#define SETRLIMIT(restxt, resource, limit) do { \
-    if ((limit) != -1) { \
-       struct rlimit rl; \
-       \
-       rl.rlim_cur = rl.rlim_max = (rlim_t)(limit); \
-       if (setrlimit((resource), &rl) == -1) \
-           syslog(LOG_NOTICE, "* setrlimit(%s, %ld) - (%s)", \
-                   (restxt), (limit), strerror(errno)); \
-    } \
-} while (/* CONSTCOND */0)
-
-
-
-/* PROTOTYPES */
-
-int                            main(int, char **);
-
-static bool                    daemon_detach(const char *, const char *);
-static void                    daemon_sighandler(int);
-static bool                    client_kill_iterator(hashnode_t *, void *);
-static void                    client_timeout(timerid_t, void *);
-static void                    pidfile_write(const char *);
-static int                     lock_check(const char *);
-static struct iface            *ifaces_parse(char *);
-
-static void                    client_resolve(void);
-static void                    exec_command(const char *, char * const *);
-
-static bool                    connection_open(const char *);
-static void                    connection_close(void);
-static struct ipaddr_node      *ipaddr_open(struct sockaddr *, const char *);
-static void                    ipaddr_close(struct ipaddr_node *);
-
-static u_int32_t               key_hash32(const void *, size_t);
-static int                     key_cmp32(const void *, const void *, size_t);
-static int                     key_pidcmp(const void *, const void *, size_t);
-static u_int32_t               key_pidhash(const void *, size_t);
-
-void                           launch_server_child_init(const char *, uid_t,
-                                                        gid_t *, int);
-
-static pid_t                   launch_server_process(uid_t, gid_t *, int);
-static void                    server_process_main(void);
-
-static pid_t                   launch_ipaddr_expire_process(uid_t, gid_t *,
-                                                            int);
-static void                    ipaddr_expire_process_main(void);
-static bool                    ipaddr_expire_process_iterator(hashnode_t *,
-                                                              void *);
-
-
-
-/* GLOBALS */
-
-/* Normal static data used for current configuration, so that clients may keep
- * their active config copy in case the server reloads it; Also is of faster
- * access than shared memory, requireing no locking for synchronization.
- */
-static struct configuration    CONF;
-
-/* Base structure to all shared memory data, for which synchronization is
- * required using locks.
- */
-static struct shmem_data       *shmem = NULL;
-
-/* Static data array mapping lock files descriptors to an index used with
- * flock(3) for the various shared memory sections.
- */
-static int                     locks[(enum shlocks)SHLOCK_MAX];
-
-/* Static client-specific data which is only significant for each children
- * process, as well as server-specific data which belongs to the listener
- * process.
- */
-static struct client_data      client;
-static struct server_data      server;
-
-
-
-/* CODE */
-
-int
-main(int argc, char **argv)
-{
-    char               *conf_file = "/usr/local/etc/mmspawnd.conf";
-    pid_t              uid;
-    gid_t              *gids;
-    int                        ngids, backlog;
-    long               facility;
-    cres_t             cres;
-    carg_t             *cargp;
-    carg_t             cargs[] = {
-       {CAT_STR, CAF_NONE, 0, 255, "CHROOT_DIR", CONF.CHROOT_DIR},
-       {CAT_STR, CAF_NONE, 1, 255, "LOCKS_PATH", CONF.LOCKS_PATH},
-       {CAT_STR, CAF_NONE, 1, 31, "LOCKS_USER", CONF.LOCKS_USER},
-       {CAT_STR, CAF_NONE, 1, 31, "LOCKS_GROUP", CONF.LOCKS_GROUP},
-       {CAT_STR, CAF_NONE, 1, 3, "LOCKS_MODE", CONF.LOCKS_MODE},
-       {CAT_STR, CAF_NONE, 1, 255, "PID_PATH", CONF.PID_PATH},
-       {CAT_STR, CAF_NONE, 1, 31, "USER", CONF.USER},
-       {CAT_STR, CAF_NONE, 1, 255, "GROUPS", CONF.GROUPS},
-       {CAT_STR, CAF_NONE, 1, 31, "LOG_FACILITY", CONF.LOG_FACILITY},
-       {CAT_STR, CAF_NONE, 1, 1023, "LISTEN_ADDRESSES",
-           CONF.LISTEN_ADDRESSES},
-       {CAT_STR, CAF_NONE, 1, 255, "COMMAND", CONF.COMMAND},
-       {CAT_STR, CAF_NONE, 0, 255, "ALOCK_PATH", CONF.ALOCK_PATH},
-       {CAT_STR, CAF_NONE, 1, 31, "ALOCK_USER", CONF.ALOCK_USER},
-       {CAT_STR, CAF_NONE, 1, 31, "ALOCK_GROUP", CONF.ALOCK_GROUP},
-       {CAT_STR, CAF_NONE, 1, 3, "ALOCK_MODE", CONF.ALOCK_MODE},
-       {CAT_STR, CAF_NONE, 0, 63, "PROCTITLE", CONF.PROCTITLE},
-       {CAT_STR, CAF_NONE, 0, 255, "STDERR_FILE", CONF.STDERR_FILE},
-       {CAT_VAL, CAF_NONE, 0, 64, "MAX_ARGUMENTS", &CONF.MAX_ARGUMENTS},
-       {CAT_VAL, CAF_NONE, 1, 65535, "LISTEN_PORT", &CONF.LISTEN_PORT},
-       {CAT_VAL, CAF_NONE, 1, 99999, "MAX_CONNECTIONS",
-           &CONF.MAX_CONNECTIONS},
-       {CAT_VAL, CAF_NONE, 1, 99999, "MAX_ADDRESSES", &CONF.MAX_ADDRESSES},
-       {CAT_VAL, CAF_NONE, 1, 99999, "MAX_PER_ADDRESS",
-           &CONF.MAX_PER_ADDRESS},
-       {CAT_VAL, CAF_NONE, 0, 99999, "CONNECTION_RATE",
-           &CONF.CONNECTION_RATE},
-       {CAT_VAL, CAF_NONE, 0, 99999, "CONNECTION_PERIOD",
-           &CONF.CONNECTION_PERIOD},
-       {CAT_VAL, CAF_NONE, 1, 99999, "COMMAND_TIMEOUT",
-           &CONF.COMMAND_TIMEOUT},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_CORE", &CONF.LIMIT_CORE},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_CPU", &CONF.LIMIT_CPU},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_DATA", &CONF.LIMIT_DATA},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_FSIZE", &CONF.LIMIT_FSIZE},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_MEMLOCK", &CONF.LIMIT_MEMLOCK},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_NOFILE", &CONF.LIMIT_NOFILE},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_NPROC", &CONF.LIMIT_NPROC},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_RSS", &CONF.LIMIT_RSS},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_STACK", &CONF.LIMIT_STACK},
-       {CAT_BOOL, CAF_NONE, 0, 0, "RESOLVE_ADDRESSES",
-           &CONF.RESOLVE_ADDRESSES},
-       {CAT_BOOL, CAF_NONE, 0, 0, "KILL_CHILDREN", &CONF.KILL_CHILDREN},
-       {CAT_BOOL, CAF_NONE, 0, 0, "RLIMITS", &CONF.RLIMITS},
-       {CAT_END, CAF_NONE, 0, 0, NULL, NULL}
-    };
-    cmap_t             cmap[] = {
-       {"LOG_AUTH", LOG_AUTH},
-       {"LOG_AUTHPRIV", LOG_AUTHPRIV},
-       {"LOG_CRON", LOG_CRON},
-       {"LOG_DAEMON", LOG_DAEMON},
-       {"LOG_FTP", LOG_FTP},
-       {"LOG_LPR", LOG_LPR},
-       {"LOG_MAIL", LOG_MAIL},
-       {"LOG_NEWS", LOG_NEWS},
-       {"LOG_SYSLOG", LOG_SYSLOG},
-       {"LOG_USER", LOG_USER},
-       {"LOG_UUCP", LOG_UUCP},
-       {NULL, 0}
-    };
-    int                        i, nifaces, errfd;
-    struct sockaddr_in server_addr;
-    struct iface       *ifaces, *tif;
-    struct pollfd      *fds;
-
-    /* Set harmless defaults */
-    *CONF.CHROOT_DIR = '\0';
-    (void) mm_strcpy(CONF.LOCKS_PATH, "/var/run/mmspawnd.lock");
-    (void) mm_strcpy(CONF.LOCKS_USER, "mmspawnd");
-    (void) mm_strcpy(CONF.LOCKS_GROUP, "mmspawnd");
-    (void) mm_strcpy(CONF.LOCKS_MODE, "400");
-    (void) mm_strcpy(CONF.PID_PATH, "/var/run/mmspawnd.pid");
-    (void) mm_strcpy(CONF.USER, "mmspawnd");
-    (void) mm_strcpy(CONF.GROUPS, "mmspawnd");
-    (void) mm_strcpy(CONF.LOG_FACILITY, "LOG_AUTHPRIV");
-    (void) mm_strcpy(CONF.LISTEN_ADDRESSES, "127.0.0.1");
-    (void) mm_strcpy(CONF.COMMAND, "/sbin/nologin");
-    *CONF.ALOCK_PATH = '\0';
-    (void) mm_strcpy(CONF.ALOCK_USER, "mmspawnd");
-    (void) mm_strcpy(CONF.ALOCK_GROUP, "mmspawnd");
-    (void) mm_strcpy(CONF.ALOCK_MODE, "400");
-    *CONF.PROCTITLE = '\0';
-    *CONF.STDERR_FILE = '\0';
-    CONF.LISTEN_PORT = 2323;
-    CONF.MAX_CONNECTIONS = 32;
-    CONF.MAX_ADDRESSES = 32;
-    CONF.MAX_PER_ADDRESS = 1;
-    CONF.CONNECTION_RATE = 5;
-    CONF.CONNECTION_PERIOD = 30;
-    CONF.MAX_ARGUMENTS = 16;
-    CONF.COMMAND_TIMEOUT = 300;
-    CONF.LIMIT_CORE = -1;
-    CONF.LIMIT_CPU = -1;
-    CONF.LIMIT_DATA = -1;
-    CONF.LIMIT_FSIZE = -1;
-    CONF.LIMIT_MEMLOCK = -1;
-    CONF.LIMIT_NOFILE = -1;
-    CONF.LIMIT_NPROC = -1;
-    CONF.LIMIT_RSS = -1;
-    CONF.LIMIT_STACK = -1;
-    CONF.RESOLVE_ADDRESSES = FALSE;
-    CONF.KILL_CHILDREN = TRUE;
-    CONF.RLIMITS = FALSE;
-
-    /* Read config file */
-    if (argc == 2)
-       conf_file = argv[1];
-    if (!mmreadcfg(&cres, cargs, conf_file)) {
-       /* Error parsing configuration file, report which */
-       (void) fprintf(stderr, "\nError parsing '%s'\n", conf_file);
-       (void) fprintf(stderr, "Error  : %s\n", mmreadcfg_strerr(cres.CR_Err));
-       if (*(cres.CR_Data))
-           (void) fprintf(stderr, "Data   : %s\n", cres.CR_Data);
-       if ((cargp = cres.CR_Keyword) != NULL) {
-           (void) fprintf(stderr, "Keyword: %s\n", cargp->CA_Keyword);
-           (void) fprintf(stderr, "Minimum: %ld\n", cargp->CA_Min);
-           (void) fprintf(stderr, "Maximum: %ld\n", cargp->CA_Max);
-       }
-       if (cres.CR_Line != -1)
-           (void) fprintf(stderr, "Line   : %d\n", cres.CR_Line);
-       (void) fprintf(stderr, "\n");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Post parsing */
-    if (!mmmapstring(cmap, CONF.LOG_FACILITY, &facility)) {
-       (void) fprintf(stderr, "\nUnknown syslog facility %s\n\n",
-                      CONF.LOG_FACILITY);
-       exit(EXIT_FAILURE);
-    }
-    if ((uid = mmgetuid(CONF.USER)) == -1) {
-       (void) fprintf(stderr, "\nUnknown USER '%s'\n\n", CONF.USER);
-       exit(EXIT_FAILURE);
-    }
-    if (!(gids = mmgetgidarray(&ngids, CONF.GROUPS))) {
-       (void) fprintf(stderr, "\nOne of following GROUPS unknown: '%s'\n\n",
-                      CONF.GROUPS);
-       exit(EXIT_FAILURE);
-    }
-    /* Initialize alock */
-    if (*CONF.ALOCK_PATH != '\0') {
-       uid_t   u;
-       gid_t   g;
-       mode_t  m;
-
-       if ((u = mmgetuid(CONF.ALOCK_USER)) == -1) {
-           (void) fprintf(stderr, "\nUnknown ALOCK_USER '%s'\n\n",
-                          CONF.ALOCK_USER);
-           exit(EXIT_FAILURE);
-       }
-       if ((g = mmgetgid(CONF.ALOCK_GROUP)) == -1) {
-           (void) fprintf(stderr, "\nUnknown ALOCK_GROUP '%s'\n\n",
-                          CONF.ALOCK_GROUP);
-           exit(EXIT_FAILURE);
-       }
-       (void) sscanf(CONF.ALOCK_MODE, "%o", &m);
-       if (m == 0 || m > 0770) {
-           (void) fprintf(stderr, "\nIllegal ALOCK_MODE '%03o'\n\n", m);
-           exit(EXIT_FAILURE);
-       }
-       if ((server.alock = open(CONF.ALOCK_PATH, O_WRONLY | O_CREAT, m))
-               == -1) {
-           (void) fprintf(stderr, "\n* main() - open(%s) - (%s)\n\n",
-                          CONF.ALOCK_PATH, strerror(errno));
-           exit(EXIT_FAILURE);
-       }
-       if (fchown(server.alock, u, g) == -1) {
-           (void) fprintf(stderr, "\n* main() - fchown(%s) - (%s)\n\n",
-                          CONF.ALOCK_PATH, strerror(errno));
-           exit(EXIT_FAILURE);
-       }
-    } else
-       server.alock = -1;
-    /* Initialize shlocks */
-    if (CONF.SHLOCKS_PATH != '\0') { /* Actually should always be true */
-       uid_t   u;
-       gid_t   g;
-       mode_t  m;
-
-       if ((u = mmgetuid(CONF.LOCKS_USER)) == -1) {
-           (void) fprintf(stderr, "\nUnknown LOCKS_USER '%s'\n\n",
-                          CONF.ALOCK_USER);
-           exit(EXIT_FAILURE);
-       }
-       if ((g = mmgetgid(CONF.LOCKS_GROUP)) == -1) {
-           (void) fprintf(stderr, "\nUnknown LOCKS_GROUP '%s'\n\n",
-                          CONF.ALOCK_GROUP);
-           exit(EXIT_FAILURE);
-       }
-       (void) sscanf(CONF.LOCKS_MODE, "%o", &m);
-       if (m == 0 || m > 0770) {
-           (void) fprintf(stderr, "\nIllegal LOCKS_MODE '%03o'\n\n", m);
-           exit(EXIT_FAILURE);
-       }
-       /* XXX */
-    }
-    if ((ifaces = ifaces_parse(CONF.LISTEN_ADDRESSES)) == NULL) {
-       (void) fprintf(stderr, "\nInvalid LISTEN_ADDRESSES\n\n");
-       exit(EXIT_FAILURE);
-    }
-    if ((server.line = _mm_strdup(CONF.COMMAND)) != NULL && (server.argv =
-               malloc(sizeof(char *) * (CONF.MAX_ARGUMENTS + 2))) != NULL) {
-       int     argc;
-
-       if (!mm_cmdparse(&server.command, &argc, server.argv, server.line,
-                   CONF.MAX_ARGUMENTS + 2)) {
-           (void) fprintf(stderr, "\nError parsing COMMAND (also check \
-MAX_ARGUMENTS)\n\n");
-           exit(EXIT_FAILURE);
-       }
-    } else {
-       (void) fprintf(stderr, "\nOut of memory\n\n");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Config file seemed right, start with initialization */
-    {
-       char    buf[128];
-
-       (void) snprintf(buf, 127, "%s%c%s", DAEMON_NAME,
-                       (*CONF.PROCTITLE != '\0' ? ':' : ' '), CONF.PROCTITLE);
-       openlog(buf, LOG_PID | LOG_NDELAY, facility);
-    }
-
-    /* Some consistency checks according to permissions */
-#ifndef NODROPPRIVS
-    if (getuid() != 0) {
-       (void) fprintf(stderr,
-                      "\nOnly the super user may start this daemon\n\n");
-       syslog(LOG_NOTICE,
-               "main() - Refused to launch for uid %d attempt (not root, \
-!NODROPPRIVS)", (int)getuid());
-       exit(EXIT_FAILURE);
-    }
-#else /* NODROPPRIVS */
-    if (getuid() == 0) {
-       (void) fprintf(stderr, "\nCompiled with NODROPPRIVS, ",
-                      "refusing to run as uid 0\n\n");
-       syslog(LOG_NOTICE, "main() - NODROPPRIVS, refusing to run as uid 0");
-       exit(EXIT_FAILURE);
-    }
-#endif /* !NODROPPRIVS */
-
-    /* Make sure that only one instance is running */
-    if ((server.runlock = lock_check(CONF.LOCK_PATH)) == -1) {
-       (void) fprintf(stderr, "\n%s already running\n\n", DAEMON_NAME);
-       syslog(LOG_NOTICE, "main() - %s already running", DAEMON_NAME);
-       exit(EXIT_FAILURE);
-    }
-
-    /* Things we want to do now in case we chroot(2) */
-    /* XXX If we want to use mmstat(3)/mmstatd(8) we should initialize the
-     * system here. However, this is a problem with mmstat(3) and chroot
-     * setups, unless an mmstatd(8) daemon runs into the chroot itself.
-     * I should fix mmstatd(8) to support chroot(2). If NetBSD nullfs mounts
-     * allowed connections to sockets, this problem would be fixed...
-     * What we could do for now is to not support mmstat(3), simply.
-     */
-
-    /* Create our locks for shared memory synchronization. These lock files
-     * (LOCK_PATH) should also be available under the new root since they
-     * need to be reopened by our children.
-     * XXX Should be done after chroot(2), with proper permissions so that
-     * we may reopen the files in children processes, Moreover, the
-     * lock_check() lock path should be independent (since outside the chroot)?
-     */
-    if (!shlocks_init(CONF.LOCK_PATH, locks, SHLOCK_MAX, TRUE)) {
-       syslog(LOG_NOTICE, "main() - shlocks_init()");
-       exit(EXIT_FAILURE);
-    }
-
-    /* If CONF.STDERR_FILE was specified, attempt to append to the file if
-     * it exists, or to create it otherwise.
-     */
-    if (*CONF.STDERR_FILE != '\0') {
-       if ((errfd = open(CONF.STDERR_FILE, O_WRONLY | O_APPEND)) == -1) {
-           if ((errfd = open(CONF.STDERR_FILE, O_CREAT | O_WRONLY, 600))
-                   == -1) {
-               syslog(LOG_NOTICE, "main() - open(%s)", CONF.STDERR_FILE);
-               exit(EXIT_FAILURE);
-           }
-       }
-    } else
-       errfd = -1;
-
-    /* Close unnecessary filedescriptors and become a daemon, chroot(2)ing
-     * if necessary. This also sets up the connection listener signal handlers.
-     */
-    if (!daemon_detach(CONF.PID_PATH, CONF.CHROOT_DIR)) {
-       syslog(LOG_NOTICE, "main() - daemon_detach()");
-       exit(EXIT_FAILURE);
-    }
-    /* Reopen lock files as needed by flock(2) */
-    if (!shlocks_init(CONF.LOCK_PATH, locks, SHLOCK_MAX, FALSE)) {
-       syslog(LOG_NOTICE, "main() - shlocks_init(FALSE)");
-       exit(EXIT_FAILURE);
-    }
-
-    /* stderr is already redirected to "/dev/null". However, we want to
-     * redirect it to CONF.STDERR_FILE if it was specified.
-     */
-    if (errfd != -1) {
-       (void) dup2(errfd, 1);
-       /* errfd always >2 */
-       (void) close(errfd);
-    }
-
-    /* Reset number of current connections to 0 and initialize the pid_t table
-     * and pool.
-     */
-    server.current_connections = 0;
-    if (!pool_init(&server.pid_pool, "pid_pool", malloc, free, NULL, NULL,
-               sizeof(struct pid_node), CONF.MAX_CONNECTIONS, 1, 1)) {
-       syslog(LOG_NOTICE, "main() - pool_init(pid_pool)");
-       exit(EXIT_FAILURE);
-    }
-    if (!hashtable_init(&server.pid_table, "pid_table", CONF.MAX_CONNECTIONS,
-               1, malloc, free, key_pidcmp, key_pidhash, FALSE)) {
-       syslog(LOG_NOTICE, "main() - hashtable_init(pid_table)");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Allocate some shared memory */
-    if ((shmem = shmem_malloc(sizeof(struct shmem_data))) == NULL) {
-       syslog(LOG_NOTICE, "main() - shmem_malloc()");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Initialize shared memory pool and table. Note that we make sure to
-     * allocate the memory in a single block, large enough, so that
-     * shmem_free() not be called by another process, which obviously would
-     * only munmap(2) within it's own process.
-     */
-    if (!pool_init(&shmem->ipaddr_pool, "ipaddr_pool",
-               shmem_malloc, shmem_free, NULL, NULL,
-               sizeof(struct ipaddr_node), CONF.MAX_ADDRESSES, 1, 1)) {
-       syslog(LOG_NOTICE, "main() - pool_init(ipaddr_pool)");
-       exit(EXIT_FAILURE);
-    }
-    if (!hashtable_init(&shmem->ipaddr_table, "ipaddr_table",
-               CONF.MAX_ADDRESSES, 1, shmem_malloc, shmem_free,
-               key_cmp32, key_hash32, FALSE)) {
-       syslog(LOG_NOTICE, "main() - hashtable_init(ipaddr_table)");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Initialize our command timers context */
-    if (!timer_ctx_init(&server.timers, malloc, free, time, alarm)) {
-       syslog(LOG_NOTICE, "main() - timer_ctx_init()");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Start our cache entry expiration process. It would have been possible
-     * to use setitimer(2) and do this into the signal handler of the main
-     * process, alternatively. However, since we already have the interprocess
-     * locking glue setup, we can keep the design simple and use a process.
-     * Further, it allows to have the resolver fill the cache from the child
-     * processes asynchroneously, without causing the main listener to block.
-     * Note that the following function also causes the child to become
-     * unprivileged.
-     */
-    if (launch_ipaddr_expire_process(uid, gids, ngids, CONF.CHROOT_PATH) < 1) {
-       syslog(LOG_NOTICE, "main() - launch_ipaddr_expire_process()");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Bind our port to the various interfaces */
-    for (nifaces = 0, tif = ifaces; *(tif->address); tif++) {
-       if ((tif->sock = socket(AF_INET, SOCK_STREAM, 0)) > -1) {
-           struct linger linger;
-
-           /* Note: These options are inherited after accept(2) */
-           i = 1;
-           if ((setsockopt(tif->sock, SOL_SOCKET, SO_REUSEADDR, &i,
-                           sizeof(int))) == -1)
-               syslog(LOG_NOTICE,
-                       "main() - setsockopt(SO_REUSEADDR %s:%d)",
-                       tif->address, (int)CONF.LISTEN_PORT);
-           i = 1;
-           if ((setsockopt(tif->sock, SOL_SOCKET, SO_KEEPALIVE, &i,
-                           sizeof(int))) == -1)
-               syslog(LOG_NOTICE,
-                       "main() - setsockopt(SO_KEEPALIVE)");
-           linger.l_onoff = 0;
-           linger.l_linger = 0;
-           if ((setsockopt(tif->sock, SOL_SOCKET, SO_LINGER, &linger,
-                           sizeof(struct linger))) != -1)
-               syslog(LOG_NOTICE,
-                       "main() - setsockopt(SO_LINGER)");
-           i = 0;
-           mm_memclr(&server_addr, sizeof(struct sockaddr_in));
-           server_addr.sin_family = AF_INET;
-           server_addr.sin_addr = tif->saddr.sin_addr;
-           server_addr.sin_port = htons(CONF.LISTEN_PORT);
-           if ((bind(tif->sock, (struct sockaddr *)(void *)&server_addr,
-                           sizeof(struct sockaddr_in))) == 0)
-               nifaces++;
-           else {
-               syslog(LOG_NOTICE,
-                       "main() - bind(%s:%d)",
-                       tif->address, (int)CONF.LISTEN_PORT);
-               (void) close(tif->sock);
-               tif->sock = -1;
-           }
-       }
-    }
-    if (nifaces == 0) {
-       syslog(LOG_NOTICE, "No interfaces (left) to listen to");
-       (void) kill(0, SIGTERM);
-       exit(EXIT_FAILURE);
-    }
-
-    /* Drop privileges definitively */
-    if (!mmdropprivs(uid, gids, ngids)) {
-       syslog(LOG_NOTICE, "Cannot change uid and gids to safe privs");
-       exit(EXIT_FAILURE);
-    }
-
-#ifndef __GLIBC__
-    setproctitle("%s Socket listener process", CONF.PROCTITLE);
-#endif /* __GLIBC__ */
-
-    /* Start listening to bound sockets */
-    backlog = CONF.MAX_ADDRESSES * CONF.MAX_PER_ADDRESS;
-    if (backlog > CONF.MAX_CONNECTIONS)
-       backlog = CONF.MAX_CONNECTIONS;
-    for (tif = ifaces; *(tif->address); tif++) {
-       if (tif->sock != -1) {
-           if ((listen(tif->sock, backlog)) == -1) {
-               syslog(LOG_NOTICE, "* main() - listen(%s)", tif->address);
-               (void) close(tif->sock);
-               tif->sock = -1;
-               nifaces--;
-           } else
-               syslog(LOG_NOTICE, "Listening on [%s:%d]",
-                       tif->address, (int)CONF.LISTEN_PORT);
-       }
-    }
-
-    /* Setup our poll() array for the interfaces we'll accept() on */
-    if ((fds = malloc(sizeof(struct pollfd) * nifaces)) != NULL) {
-       for (i = 0, tif = ifaces; *(tif->address) != '\0'; tif++) {
-           if (tif->sock != -1) {
-               fds[i].fd = tif->sock;
-               fds[i].events = POLLIN;
-               fds[i].revents = 0;
-               i++;
-           }
-       }
-    } else {
-       syslog(LOG_NOTICE, "Out of memory");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Listen for connections and dispatch them to independant processes */
-    syslog(LOG_NOTICE, "Launched for uid %d with configuration file '%s', \
-listening for connections on port %d. Service is '%s'.",
-       uid, conf_file, (int)CONF.LISTEN_PORT, CONF.COMMAND);
-    for (;;) {
-       int                     i, sock, nifaces2;
-       socklen_t               addrl = sizeof(struct sockaddr);
-       struct sockaddr         addr;
-       struct ipaddr_node      *ipn = NULL;
-       char                    ipaddr[20];
-
-       while ((nifaces2 = poll(fds, nifaces, -1)) == -1 && errno == EINTR) ;
-       for (i = 0; i < nifaces && nifaces2 > 0; i++) {
-           if (fds[i].revents & POLLIN) {
-               nifaces2--;
-               if ((sock = accept(fds[i].fd, &addr, &addrl)) != -1) {
-                   bool        connection;
-
-                   /* We got a connection, verify if within allowed limits. */
-                   mm_strcpy(ipaddr, "0.0.0.0");
-                   (void) inet_ntop(AF_INET,
-                           &(((struct sockaddr_in *)&addr)->sin_addr),
-                           ipaddr, 19);
-                   if ((connection = connection_open(ipaddr)) &&
-                           (ipn = ipaddr_open(&addr, ipaddr)) != NULL) {
-                       pid_t   pid;
-
-                       /* Attempt to launch a new process */
-                       if ((pid = fork()) == -1) {
-                           /* fork(2) failure! Be graceful. Fortunately,
-                            * this is extremely unlikely to occur unless
-                            * the configuration allows unfair limits.
-                            */
-                           DEBUG_PRINTF("main", "fork()");
-                           ipaddr_close(ipn);
-                           connection_close();
-                           (void) close(sock);
-                       } else if (pid > 0) {
-                           struct pid_node     *pnod;
-
-                           /* Parent, close client socket, record child
-                            * process, and continue. As we use a preallocated
-                            * pool of enough nodes for the allowed limits,
-                            * no need for error checking at pool_alloc().
-                            * If timer_init() fails, 0 is set as timerid_t,
-                            * which is also safe.
-                            */
-                           (void) close(sock);
-                           pnod = (struct pid_node *)pool_alloc(
-                                   &server.pid_pool, FALSE);
-                           pnod->pid = pid;
-                           /* Note: We use an auto-restarting timer because
-                            * otherwise the SIGALRM handler can remove it
-                            * while the SIGCHLD handler attempts to remove it,
-                            * after the SIGCHLD handler verified if it existed
-                            * generating a debug warning otherwise.
-                            */
-                           pnod->tid = timer_init(&server.timers, time(NULL),
-                                   (u_int32_t)CONF.COMMAND_TIMEOUT,
-                                   client_timeout, pnod, TRUE);
-                           pnod->ipn = ipn;
-                           (void) hashtable_link(&server.pid_table,
-                                   (hashnode_t *)pnod, &pnod->pid,
-                                   sizeof(pid_t), FALSE);
-                       } else {
-                           /* Child successfully launched */
-                           struct sigaction    act;
-
-#ifndef __GLIBC__
-                           setproctitle("%s Client server process",
-                                   CONF.PROCTITLE);
-#endif /* __GLIBC__ */
-
-                           /* We create our own process group so that the
-                            * process after execve(2) could not kill(0)
-                            * causing the listener process to exit.
-                            * It also allows us to optionally not interrupt
-                            * currently served client when we restart.
-                            */
-                           (void) setsid();
-
-                           /* Change signal handling policy. If we do not
-                            * restore the signals we ignore to the default
-                            * action, they will be ignored by the process
-                            * after execve(2). Signals we are handling
-                            * will automatically be restored to the default
-                            * action.
-                            */
-                           act.sa_handler = SIG_DFL;
-                           act.sa_flags = SA_NOCLDSTOP;
-                           (void) sigemptyset(&act.sa_mask);
-
-                           (void) sigaction(SIGTTOU, &act, NULL);
-                           (void) sigaction(SIGTTIN, &act, NULL);
-                           (void) sigaction(SIGTSTP, &act, NULL);
-                           (void) sigaction(SIGPIPE, &act, NULL);
-
-                           /* Close bound sockets which this process shouldn't
-                            * have access to. XXX We could use fcntl(3) to
-                            * change socket inheritance at execve(2)...
-                            */
-                           for (tif = ifaces; *(tif->address); tif++) {
-                               if (tif->sock != -1) {
-                                   (void) close(tif->sock);
-                                   tif->sock = -1;
-                               }
-                           }
-
-                           /* stderr is already redirected to "/dev/null",
-                            * or to our debugging CONF.STDERR_FILE file.
-                            * Make sure that stdin and stdout are redirected
-                            * to the client socket, and to close the
-                            * extraneous filedescriptor.
-                            */
-                           (void) dup2(sock, 0);
-                           (void) dup2(sock, 1);
-                           /* sock always >2 */
-                           (void) close(sock);
-
-                           /* Let child know and remember these */
-                           client.ipn = ipn;
-                           client.saddr = addr;
-                           client.ipaddr = (const char *)ipaddr;
-
-                           /* Reopen lock files as needed for flock(2).
-                            * We don't need to reopen alock since only the
-                            * parent ever locks it.
-                            */
-                           (void) shlocks_init(CONF.LOCK_PATH, locks,
-                                               SHLOCK_MAX, FALSE);
-                           /* Resolve if CONF.RESOLVE_ADDRESSES */
-                           client_resolve();
-
-                           /* We do not need to hold the lock files any
-                            * longer, and in fact we do not want to let
-                            * the process access them, especially if the
-                            * administrator sets up the service to not kill
-                            * currently running children if the service is
-                            * shut down.
-                            */
-                           (void) shlocks_destroy(CONF.LOCK_PATH, locks,
-                                       (enum shlocks)SHLOCK_MAX, FALSE);
-                           (void) close(server.runlock);
-                           (void) close(server.alock);
-
-                           /* If enabled, attempt to set setrlimit(2) */
-                           if (CONF.RLIMITS) {
-                               SETRLIMIT("RLIMIT_CORE", RLIMIT_CORE,
-                                       CONF.LIMIT_CORE);
-                               SETRLIMIT("RLIMIT_CPU", RLIMIT_CPU,
-                                       CONF.LIMIT_CPU);
-                               SETRLIMIT("RLIMIT_DATA", RLIMIT_DATA,
-                                       CONF.LIMIT_DATA);
-                               SETRLIMIT("RLIMIT_FSIZE", RLIMIT_FSIZE,
-                                       CONF.LIMIT_FSIZE);
-                               SETRLIMIT("RLIMIT_MEMLOCK", RLIMIT_MEMLOCK,
-                                       CONF.LIMIT_MEMLOCK);
-                               SETRLIMIT("RLIMIT_NOFILE", RLIMIT_NOFILE,
-                                       CONF.LIMIT_NOFILE);
-                               SETRLIMIT("RLIMIT_NPROC", RLIMIT_NPROC,
-                                       CONF.LIMIT_NPROC);
-                               SETRLIMIT("RLIMIT_RSS", RLIMIT_RSS,
-                                       CONF.LIMIT_RSS);
-                               SETRLIMIT("RLIMIT_STACK", RLIMIT_STACK,
-                                       CONF.LIMIT_STACK);
-                           }
-
-                           /* We can finally attempt to launch our external
-                            * executable.
-                            */
-                           exec_command(server.command,
-                                   (char * const *)server.argv);
-                           /* NOTREACHED */
-                       }
-                   } else {
-                       /* Limits have been exceeded, close socket immediately
-                        */
-                       (void) close(sock);
-                       if (connection)
-                           connection_close();
-                       if (ipn != NULL)
-                           ipaddr_close(ipn);
-                   }
-               } else
-                   DEBUG_PRINTF("main", "accept()");
-           }
-       }
-    }
-
-    /* NOTREACHED */
-    exit(EXIT_SUCCESS);
-}
-
-
-/* Uses fork(2) and setsid(2) to become a daemon, and detaches from the
- * current tty. Also calls chroot(2) and chdir(2) if a jail directory is
- * supplied. Returns either successful or not (TRUE, FALSE).
- */
-static bool
-daemon_detach(const char *pidfile, const char *jail)
-{
-    int        pid;
-
-#ifdef NODETACH
-    pid = getpid();
-#else /* NODETACH */
-    if ((pid = fork()) != -1)
-#endif /* !NODETACH */
-    {
-
-#ifndef NODETACH
-       if (pid > 0) {
-           /* Parent */
-           exit(EXIT_SUCCESS);
-       } else
-#endif /* !NODETACH */
-       {
-           int                 fd;
-           struct sigaction    act;
-
-           /* Child */
-           (void) setsid();
-           (void) chdir("/");
-           if ((fd = open("/dev/null", O_RDWR)) != -1) {
-               (void) dup2(fd, 0);
-               (void) dup2(fd, 1);
-               (void) dup2(fd, 2);
-               if (fd > 2)
-                   (void) close(fd);
-           }
-           pidfile_write(pidfile);
-
-           /* Chroot if required */
-           if (jail != NULL && *jail != '\0') {
-               if ((chroot(jail)) == -1) {
-                   syslog(LOG_NOTICE,
-                           "daemon_detach() - Could not chroot(2) to '%s'",
-                           jail);
-                   exit(EXIT_FAILURE);
-               }
-               (void) chdir("/");
-           }
-
-           /* Setup our server signal handlers. We also want to make
-            * sure that we catch SIGCHLD for every process that exits.
-            * (we don't need SIGCHLD events for process STOP however).
-            */
-           act.sa_handler = daemon_sighandler;
-           act.sa_flags = SA_NOCLDSTOP;
-           (void) sigemptyset(&act.sa_mask);
-
-           (void) sigaction(SIGTERM, &act, NULL);
-           (void) sigaction(SIGINT, &act, NULL);
-           (void) sigaction(SIGCHLD, &act, NULL);
-           (void) sigaction(SIGSEGV, &act, NULL);
-           (void) sigaction(SIGALRM, &act, NULL);
-
-           act.sa_handler = SIG_IGN;
-           (void) sigaction(SIGTTOU, &act, NULL);
-           (void) sigaction(SIGTTIN, &act, NULL);
-           (void) sigaction(SIGTSTP, &act, NULL);
-           (void) sigaction(SIGPIPE, &act, NULL);
-
-           (void) umask(0);
-
-           return TRUE;
-       }
-    }
-
-    return FALSE;
-}
-
-
-/* This signal handler takes care of wanted signals in the TCP listener
- * server (parent process).
- */
-static void
-daemon_sighandler(int sig)
-{
-
-    switch (sig) {
-    case SIGSEGV:
-       syslog(LOG_NOTICE, "Exiting (SIGSEGV!)");
-       goto end;
-       break;
-    case SIGTERM:
-       syslog(LOG_NOTICE, "Exiting (SIGTERM)");
-       goto end;
-       break;
-    case SIGINT:
-       syslog(LOG_NOTICE, "Exiting (SIGINT)");
-       goto end;
-       break;
-    case SIGALRM:
-       /* The maximum command timeout occurred for at least one of our
-        * children processes. We then take care to kill it. Since we do
-        * not handle network inactivity timeout between the client and
-        * the command's process yet, the maximum timeout should be set at
-        * a reasonable value. It currently consists of the only way to
-        * kill hanging connections which did not generate any network error
-        * or disconnection event.
-        */
-       timer_ctx_execute(&server.timers, time(NULL));
-       break;
-    case SIGCHLD:
-       {
-           /* At least one children process exited. We evaluate the reason
-            * and free up resources held for it.
-            */
-           int                 status = 0;
-           pid_t               pid;
-           struct pid_node     *pn;
-
-           while ((pid = wait3(&status, WNOHANG, NULL)) == -1 &&
-                   errno == EINTR) ;
-           if (pid != -1) {
-               bool    quit = FALSE;
-
-               if (WIFSIGNALED(status)) {
-                   syslog(LOG_NOTICE, "Child %d received signal %d", (int)pid,
-                           WTERMSIG(status));
-                   quit = TRUE;
-               }
-               if (WIFEXITED(status)) {
-                   if (WEXITSTATUS(status) != 0)
-                       syslog(LOG_NOTICE, "Child %d terminated with code %d",
-                               (int)pid, WEXITSTATUS(status));
-                   else
-                       syslog(LOG_NOTICE, "Child %d terminated normally",
-                               (int)pid);
-                   quit = TRUE;
-               }
-               if (quit) {
-                   /* We have the pid of the process which just exited.
-                    * We must decrease the total connections counter as well
-                    * as the connections counter for that address.
-                    * We must do this here since execve(2) does not return
-                    * on success. We use the hashtable_t we setup to link
-                    * pid_t -> struct ipaddr_node *.
-                    */
-                   if ((pn = (struct pid_node *)hashtable_lookup(
-                                   &server.pid_table, &pid,
-                                   sizeof(pid_t))) != NULL) {
-                       connection_close();
-                       ipaddr_close(pn->ipn);
-                       timer_destroy(&server.timers, time(NULL), pn->tid);
-                       hashtable_unlink(&server.pid_table, (hashnode_t *)pn);
-                       (void) pool_free((pnode_t *)pn);
-                   }
-               }
-           }
-       }
-       break;
-    }
-
-    return;
-
-end:
-    /* Cleanly exit all processes. Because we use setsid(2) in the children,
-     * We use our table of still active children processes instead of a single
-     * kill(2) on the whole process group. We do that too afterwards so that
-     * we cleanup our server-side processes afterwards.
-     */
-    if (CONF.KILL_CHILDREN)
-       hashtable_iterate(&server.pid_table, client_kill_iterator, NULL);
-    {
-       struct sigaction        act;
-
-       act.sa_handler = SIG_IGN;
-       act.sa_flags = SA_NOCLDSTOP;
-       (void) sigemptyset(&act.sa_mask);
-
-       (void) sigaction(SIGTERM, &act, NULL);
-    }
-    (void) kill(0, SIGTERM);
-    shlocks_destroy(CONF.LOCK_PATH, locks, (enum shlocks)SHLOCK_MAX, TRUE);
-    shmem_freeall();
-    exit(EXIT_SUCCESS);
-}
-
-
-/* ARGSUSED */
-static bool
-client_kill_iterator(hashnode_t *hnod, void *udata)
-{
-
-    (void) kill(((struct pid_node *)hnod)->pid, SIGTERM);
-
-    return TRUE;
-}
-
-
-/* ARGSUSED */
-static void
-client_timeout(timerid_t tid, void *udata)
-{
-    struct pid_node    *pnode = (struct pid_node *)udata;
-
-    /* Just send a SIGTERM to the offending process, we'll handle the cleanup
-     * in SIGCHLD signal handler as usual.
-     */
-    syslog(LOG_NOTICE, "Killing child %d for total timeout (%ld seconds)",
-           (int)pnode->pid, CONF.COMMAND_TIMEOUT);
-    (void) kill(pnode->pid, SIGTERM);
-}
-
-
-/* Writes our process ID number to specified file. To be called before
- * chroot(2) or dropping privileges.
- */
-static void
-pidfile_write(const char *file)
-{
-    char       str[16];
-    int                fd;
-
-    if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600)) != -1) {
-       (void) snprintf(str, 15, "%d\n", getpid());
-       (void) write(fd, str, mm_strlen(str));
-       (void) close(fd);
-    } else
-       DEBUG_PRINTF("pidfile_write", "open(%s)", file);
-}
-
-
-/* This uses an fd which remains open in child processes, if they close it the
- * lock is released automatically by the process. Returns -1 if the lock
- * is already held, or a filedescriptor to the lock on success.
- */
-static int
-lock_check(const char *file)
-{
-    int        fd;
-
-    if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600)) != -1) {
-       if ((flock(fd, LOCK_EX | LOCK_NB)) == 0)
-           return fd;
-       (void) close(fd);
-    } else
-       DEBUG_PRINTF("lock_check", "open(%s)", file);
-
-    return -1;
-}
-
-
-/* Simple function to parse the interfaces specified on a line */
-static struct iface *
-ifaces_parse(char *addresses)
-{
-    struct iface       *ifaces;
-    char               *ips[65];
-    struct sockaddr_in saddr;
-    int                        n, i;
-
-    ifaces = NULL;
-
-    if (addresses != NULL && *addresses != '\0') {
-       if ((n = mm_straspl(ips, addresses, 64)) > 0) {
-           if ((ifaces = malloc(sizeof(struct iface) * (n + 1))) != NULL) {
-               /* Setup our array */
-               for (i = 0; i < n; i++) {
-                   mm_memclr(&saddr, sizeof(struct sockaddr_in));
-                   if ((inet_aton(ips[i], &(saddr.sin_addr))) == 1) {
-                       (void) mm_strncpy(ifaces[i].address, ips[i], 15);
-                       ifaces[i].sock = -1;
-                       ifaces[i].saddr = saddr;
-                       *(ifaces[i + 1].address) = '\0';
-                   } else {
-                       syslog(LOG_NOTICE,
-                               "ifaces_parse() - Invalid address [%s]",
-                               ips[i]);
-                       free(ifaces);
-                       ifaces = NULL;
-                       break;
-                   }
-               }
-           }
-       }
-    }
-
-    return ifaces;
-}
-
-
-/* Internal function to resove the hostname of the IP address of a connected
- * client and cache it (if RESOLVE_ADDRESSES was enabled).
- */
-static void
-client_resolve(void)
-{
-
-    if (CONF.RESOLVE_ADDRESSES) {
-       if (*client.ipn->hostname == '\0') {
-           int err;
-
-           while ((err = flock(locks[SHLOCK_IPADDR], LOCK_EX)) == -1 &&
-                   errno == EINTR) ;
-           if (err == 0) {
-               if (*client.ipn->hostname == '\0') {
-                   if ((getnameinfo(&client.saddr, sizeof(struct sockaddr_in),
-                                   client.ipn->hostname, 64, NULL, 0, 0))
-                           != 0)
-                       DEBUG_PRINTF("client_resolve", "getnameinfo(%s)",
-                               client.ipaddr);
-               }
-               (void) flock(locks[SHLOCK_IPADDR], LOCK_UN);
-           }
-       }
-       syslog(LOG_NOTICE, "Connection from %s (%s)", client.ipn->hostname,
-               client.ipaddr);
-    } else
-       syslog(LOG_NOTICE, "Connection from %s", client.ipaddr);
-}
-
-
-/* Safely executes the specified command, or exits.
- * This function never returns to the caller.
- * The command line can be parsed using mmstring(3)'s mm_cmdparse() first.
- * Perform sanity checking on the executable we will be launching.
- * We want to make sure that it is executable, but read-only, and that
- * it has no setuid/setgid bit set. We also ensure that it consists of
- * an executable rather than a script requireing an interpreter.
- * We also verify that the file is owned by the superuser.
- * We perform no globbing whatsoever and do not want to use a shell.
- */
-static void
-exec_command(const char *path, char * const *argv)
-{
-    struct stat                st;
-    mode_t             mode;
-    int                        fd;
-    unsigned char      buf[4];
-    char               *const env[1] = {NULL};
-
-    /* First make sure that command exists and is a regular file */
-    if (lstat(path, &st) != 0) {
-       syslog(LOG_NOTICE, "* exec_command() - lstat(%s) - (%s)", path,
-               strerror(errno));
-       exit(EXIT_FAILURE);
-    }
-    if (!S_ISREG(st.st_mode)) {
-       syslog(LOG_NOTICE, "* exec_command() - Not regular file (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    /* Reject it if it has any setuid/setgid bit set */
-    mode = st.st_mode & ~S_IFMT;
-    if (mode & S_ISUID) {
-       syslog(LOG_NOTICE, "* exec_command() - setuid file (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    if (mode & S_ISGID) {
-       syslog(LOG_NOTICE, "* exec_command() - setgid file (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    /* Has to be owned by root user for more safety */
-    if (st.st_uid != 0) {
-       syslog(LOG_NOTICE, "* exec_command() - Not owned by uid 0 (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    /* access(2) is safer than testing the mode bits. Make sure that we cannot
-     * write to the file, but that we can read and execute it.
-     */
-    if (access(path, W_OK) == 0) {
-       syslog(LOG_NOTICE, "* exec_command() - File writable (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    if (access(path, R_OK | X_OK) == -1) {
-       syslog(LOG_NOTICE, "* exec_command() - Not read/exec (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    /* Now make sure that it does not consist of a script. We only support
-     * ELF executables for now for simplicity (static or dynamic ones).
-     */
-    if ((fd = open(path, O_RDONLY)) == -1) {
-       syslog(LOG_NOTICE, "* exec_command() - open(%s) - (%s)", path,
-               strerror(errno));
-       exit(EXIT_FAILURE);
-    }
-    if (read(fd, buf, 4) != 4) {
-       syslog(LOG_NOTICE, "* exec_command() - read(%s) - (%s)", path,
-               strerror(errno));
-       (void) close(fd);
-       exit(EXIT_FAILURE);
-    }
-    (void) close(fd);
-    if (buf[1] != 'E' || buf[2] != 'L' || buf[3] != 'F') {
-       syslog(LOG_NOTICE, "* exec_command() - Not ELF file (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-
-    /* Finally attempt execution */
-    (void) execve(path, argv, env);
-
-    /* If we reach this point, execve(2) failed, and we must use _exit(2) for
-     * safety in this case.
-     */
-    _exit(EXIT_FAILURE);
-}
-
-
-/* If the maximum number of allowed connections has not been reached, increases
- * the counter and returns TRUE. Returns FALSE otherwise, in which case the
- * server should not allow more clients.
- */
-static bool
-connection_open(const char *ipaddr)
-{
-
-    if (server.current_connections == 0 && server.alock != -1) {
-       /* Attempt to lock alock */
-       if ((flock(server.alock, LOCK_EX | LOCK_NB)) == -1) {
-           syslog(LOG_NOTICE, "Refusing %s (ALOCK_PATH currently locked)",
-                   ipaddr);
-           return FALSE;
-       }
-    }
-    if (server.current_connections < CONF.MAX_CONNECTIONS) {
-       server.current_connections++;
-       return TRUE;
-    }
-    syslog(LOG_NOTICE, "Refusing %s (MAX_CONNECTIONS reached = %d)",
-           ipaddr, server.current_connections);
-
-    return FALSE;
-}
-
-
-/* Decreases the current number of total connections counter. */
-static void
-connection_close(void)
-{
-
-    if (server.current_connections > 0)
-       server.current_connections--;
-    else
-       DEBUG_PRINTF("connection_close", "server.current_connections < 1 !");
-    if (server.current_connections == 0 && server.alock != -1) {
-       /* Release alock */
-       (void) flock(server.alock, LOCK_UN);
-    }
-}
-
-
-/* These use shared memory and provide a nice API for use by the server. */
-
-/* If necessary, adds the address to the list of currently active connections.
- * If the address already was present, makes sure that it has not reached it's
- * maximum number of allowed connections and connection rate limits, and
- * increases it's counter. Returns a pointer to the ipaddr_node on success,
- * or NULL if the server should reject the connection, in which case the
- * reason and address are automatically logged via syslog(3) and mmstat(3).
- */
-static struct ipaddr_node *
-ipaddr_open(struct sockaddr *saddr, const char *ipaddr)
-{
-    struct ipaddr_node *ipn = NULL;
-    bool               ok = FALSE;
-    time_t             now = time(NULL);
-    int                        err;
-
-    /* Make sure that we respect connection rates and limits for the addresses.
-     */
-    while ((err = flock(locks[SHLOCK_IPADDR], LOCK_EX)) == -1 &&
-           errno == EINTR) ;
-    if (err == 0) {
-       struct sockaddr_in *sinaddr = (struct sockaddr_in *)saddr;
-
-       if ((ipn = (struct ipaddr_node *)hashtable_lookup(&shmem->ipaddr_table,
-                       &sinaddr->sin_addr.s_addr, sizeof(u_int32_t)))
-               == NULL) {
-           /* Create new entry */
-           if (HASHTABLE_NODES(&shmem->ipaddr_table) < CONF.MAX_ADDRESSES) {
-               if ((ipn = (struct ipaddr_node *)pool_alloc(
-                               &shmem->ipaddr_pool, FALSE)) != NULL) {
-                   /* Rate limiting and total connections initialization */
-                   LR_INIT(&ipn->lr, CONF.CONNECTION_RATE,
-                           CONF.CONNECTION_PERIOD, now);
-                   ipn->connections = 0;
-                   /* Cache nodes initialization */
-                   ipn->address = *saddr;
-                   *ipn->hostname = '\0';
-                   (void) hashtable_link(&shmem->ipaddr_table,
-                          (hashnode_t *)ipn,
-                           &((struct sockaddr_in *)&ipn->address)->
-                           sin_addr.s_addr, sizeof(u_int32_t), FALSE);
-               } else
-                   DEBUG_PRINTF("ipaddr_open", "pool_alloc()");
-           } else {
-               syslog(LOG_NOTICE,
-                       "Refusing %s for exceeded number of addresses (%ld)",
-                       ipaddr, CONF.MAX_ADDRESSES);
-           }
-       }
-       if (ipn != NULL) {
-           /* Either the node was found or successfully created */
-           if (ipn->connections < CONF.MAX_PER_ADDRESS) {
-               if (CONF.CONNECTION_RATE > 0) {
-                   if (lr_allow(&ipn->lr, 1, now, FALSE))
-                       ok = TRUE;
-                   else {
-                       syslog(LOG_NOTICE,
-                               "Refusing %s for exceeded connection rate \
-(%ld connections in %ld seconds, %ld seconds left to clear)",
-                       ipaddr, LR_POSTS(&ipn->lr), CONF.CONNECTION_PERIOD,
-                       LR_REMAINS(&ipn->lr, now));
-                   }
-               } else
-                   ok = TRUE;
-           } else {
-               syslog(LOG_NOTICE, "Refusing %s for exceeded number of \
-connections per address (%ld)", ipaddr, CONF.MAX_PER_ADDRESS);
-           }
-       }
-
-       if (ok)
-           ipn->connections++;
-       else
-           ipn = NULL;
-
-       (void) flock(locks[SHLOCK_IPADDR], LOCK_UN);
-    }
-
-    return ipn;
-}
-
-
-/* Decreases the current number of connections for the specified address, and
- * if necessary, frees the entry from the table if no more connections exist
- * for this address. The node is expected to exist and to represent the right
- * one obtained from ipaddr_open().
- */
-static void
-ipaddr_close(struct ipaddr_node *ipn)
-{
-
-    if (ipn != NULL) {
-       int     err;
-
-       while ((err = flock(locks[SHLOCK_IPADDR], LOCK_EX)) == -1 &&
-               errno == EINTR) ;
-       if (err == 0) {
-           ipn->connections--;
-           /* Leave the cache service process delete the entries, which
-            * allows us to keep statistics for rate limiting, as well as
-            * cache hostnames on a per-address basis.
-            */
-           (void) flock(locks[SHLOCK_IPADDR], LOCK_UN);
-       }
-    }
-}
-
-
-/* A quick hashtable_hash() and memcmp() replacements which already deal with
- * unique 32-bit values.
- */
-
-/* ARGSUSED */
-static u_int32_t
-key_hash32(const void *data, size_t len)
-{
-
-    return *((u_int32_t *)data);
-}
-
-/* ARGSUSED */
-static int
-key_cmp32(const void *src, const void *dst, size_t len)
-{
-
-    return *((u_int32_t *)src) - *((u_int32_t *)dst);
-}
-
-/* And to make things right, to not assume that pid_t is a u_int32_t, do
- * the same.
- */
-
-/* ARGSUSED */
-static u_int32_t
-key_pidhash(const void *data, size_t len)
-{
-
-    return (u_int32_t)*((pid_t *)data);
-}
-
-/* ARGSUSED */
-static int
-key_pidcmp(const void *src, const void *dst, size_t len)
-{
-
-    return *((pid_t *)src) - *((pid_t *)dst);
-}
-
-
-/* Useful function for use by launch_server_process() and
- * launch_ipaddress_expire_process() initialization
- */
-void
-launch_server_child_init(const char *func, uid_t uid, gid_t *gids, int ngids)
-{
-
-    /* Reopen lock files as needed for flock(2) */
-    if (shlocks_reopen(CONF.LOCK_PATH, locks, SHLOCK_MAX) == -1) {
-       syslog(LOG_NOTICE, "%s - Could not reopen lock files - %s",
-               func, strerror(errno));
-       (void) kill(getppid(), SIGTERM);
-       exit(EXIT_FAILURE);
-    }
-
-    /* chroot(2) if necessary */
-    if (CONF.CHROOT_PATH != '\0') {
-       if ((chroot(chroot_path)) == -1) {
-           syslog(LOG_NOTICE, "%s - Could not chroot(2) to '%s' - %s",
-                   func, CONF.CHROOT_PATH, strerror(errno));
-           (void) kill(getppid(), SIGTERM);
-           exit(EXIT_FAILURE);
-       }
-       (void) chdir("/");
-    }
-
-    /* Drop privileges */
-    if (!mmdropprivs(uid, gids, ngids)) {
-       syslog(LOG_NOTICE, "%s - Cannot change uid and gids to safe privs",
-               func);
-       (void) kill(getppid(), SIGTERM);
-       (void) exit(EXIT_FAILURE);
-    }
-}
-
-
-/* Launches the main server program, listening for connections and dispatching
- * them to children processes.
- */
-static pid_t
-launch_server_process(uid_t uid, gid_t *gids, int ngids)
-{
-       /* XXX */
-}
-
-static void
-server_process_main(void)
-{
-       /* XXX */
-}
-
-
-/* Launches the ipaddress-hostname-rate cache entry expiration process,
- * a kind of asynchroneous garbage collector.
- */
-static pid_t
-launch_ipaddr_expire_process(uid_t uid, gid_t *gids, int ngids)
-{
-    pid_t      pid = -1;
-
-    if ((pid = fork()) == 0) {
-       struct sigaction        act;
-
-       /* Reset default signal action */
-       act.sa_handler = SIG_DFL;
-       act.sa_flags = SA_NOCLDSTOP;
-       (void) sigemptyset(&act.sa_mask);
-
-       (void) sigaction(SIGTERM, &act, NULL);
-       (void) sigaction(SIGINT, &act, NULL);
-       (void) sigaction(SIGCHLD, &act, NULL);
-       (void) sigaction(SIGSEGV, &act, NULL);
-
-       /* Release runlock which only our parent should hold */
-       (void) close(server.runlock);
-
-       /* Will reopen lock files, chroot(2) and drop privileges */
-       launch_server_child_init("launch_ipaddr_expire_process()",
-               uid, gids, ngids);
-
-       /* Finally lanch main process loop */
-       ipaddr_expire_process_main();
-       /* NOTREACHED */
-    }
-
-    /* Parent */
-    return pid;
-}
-
-/* This process can run independently and manage the ipaddr cache entry
- * expiration events.
- */
-static void
-ipaddr_expire_process_main(void)
-{
-    struct ipaddr_expire_process_iterator_udata        data;
-
-#ifndef __GLIBC__
-    setproctitle("%s Cache service process", CONF.PROCTITLE);
-#endif /* __GLIBC__ */
-
-    /* Set initial timeout to maximum allowed */
-    data.soonest = CONF.CONNECTION_PERIOD;
-    for (;;) {
-       int     err;
-
-       /* Sleep until it is known that at least one node expired */
-       (void) sleep(data.soonest);
-       /* Tell our iterator function the current time and the maximum
-        * allowed time to wait to
-        */
-       data.current = time(NULL);
-       data.soonest = CONF.CONNECTION_PERIOD;
-       /* Lock table, reset expired nodes, garbage collect, and set
-        * data.soonest to the delay of the soonest next expireing node.
-        */
-       while ((err = flock(locks[SHLOCK_IPADDR], LOCK_EX)) == -1 &&
-               errno == EINTR) ;
-       if (err == 0) {
-           if (HASHTABLE_NODES(&shmem->ipaddr_table) > 0)
-               hashtable_iterate(&shmem->ipaddr_table,
-                       ipaddr_expire_process_iterator, &data);
-           (void) flock(locks[SHLOCK_IPADDR], LOCK_UN);
-       }
-    }
-    /* NOTREACHED */
-}
-
-/* Internally used by the cache events expiration process */
-static bool
-ipaddr_expire_process_iterator(hashnode_t *hnod, void *udata)
-{
-    struct ipaddr_node         *node = (struct ipaddr_node *)hnod;
-    struct ipaddr_expire_process_iterator_udata *data = udata;
-    time_t                     rem;
-
-    /* If the node expired, reset it. For nodes which do not, record the
-     * soonest to expire node's delay. For those which expire and for which
-     * no connections exist anymore, expunge them.
-     */
-    if ((rem = LR_REMAINS(&node->lr, data->current)) == 0) {
-       /* This entry expired */
-       if (node->connections == 0) {
-           /* Safe to expunge this entry */
-           hashtable_unlink(&shmem->ipaddr_table, (hashnode_t *)node);
-           (void) pool_free((pnode_t *)node);
-       } else {
-           /* Reset it */
-           LR_EXPIRE(&node->lr, data->current);
-           rem = LR_REMAINS(&node->lr, data->current);
-       }
-    }
-    if (rem != 0 && data->soonest > rem)
-       data->soonest = rem;
-
-    return TRUE;
-}
diff --git a/mmsoftware/mmspawnd/mmspawnd.conf.5 b/mmsoftware/mmspawnd/mmspawnd.conf.5
deleted file mode 100644 (file)
index d2d04d7..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-.\" $Id: mmspawnd.conf.5,v 1.12 2003/11/14 08:04:19 mmondor Exp $
-.\"
-.\" Copyright (C) 2003, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\" 5. Redistribution of source code may not be released under the terms of
-.\"    any GNU Public License derivate.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd October 28, 2003
-.Dt MMSPAWND.CONF 5
-.Os mmsoftware
-.Sh NAME
-.Nm mmspawnd.conf
-.Nd
-.Xr mmspawnd.conf 5
-configuration file for
-.Xr mmspawnd 8
-.Sh DESCRIPTION
-The
-.Nm /usr/local/etc/mmspawnd.conf
-file may contain one or more keyword/value pairs per line, empty lines or
-comments.  A ';' or '#' character causes all other characters to be considered
-as a comment, and to be ignored, until the end of the current line. It is
-very important to enclose the value for a keyword in double quotes ('"'
-characters) if the following characters are found in it: ';', '#', space and
-tab. It is allowed to use an equal sign '=' between the keyword name and it's
-argument. Here are documented the various possible keywords and their
-allowed values, as well as their defaults.
-.Pp
-.Ss Service administration parameters
-.Pp
-.Bl -tag -width indent -offset indent
-.It Nm CHROOT_DIR Ar "directory"
-If specified and non-empty, causes the daemon to use
-.Xr chroot 2
-at initialization so that it becomes jailed into the wanted alternative root
-directory. Obviously, all required files for the application should have a copy
-within the new root (this may include files such as
-.Nm /etc/resolv.conf ,
-.Nm /etc/hosts ,
-.Nm /etc/passwd ,
-.Nm /etc/group ,
-a few shared libraries, the executable binary to be launched, and so on,
-as required by the application and libc.
-.It Nm LOCK_PATH Ar "fullpath"
-Specifies the location where the internal synchronization (and anti-recursive
-runlock) are to be created (before chrooting). Should consist of an absolute
-full pathname including a filename, after which will automatically be postfixed
-extensions for the various locks.
-When several server instances are run concurrently to serve multiple services,
-the name of the lock files should be different for each to not conflict.
-.It Nm PID_PATH Ar "fullpath"
-Tells where to store the file holding the server process ID to be killed with
-.Dv SIGTERM
-(sig 15) to cause the server to cleanly exit. This is done before chrooting.
-When several server instances are run concurrently to serve multiple services,
-the name of the PID files should be different for each to not conflict.
-.It Nm ALOCK_PATH Ar "fullpath"
-If specified and non-empty, this enables a special feature of
-.Nm mmspawnd
-which allows advisory locking to be used on a special file with third
-party applications to synchronize with the service. This obviously should
-be configured with care, but is most useful with some setups. The file
-will be created before calling
-.Xr chroot 2
-and thus anywhere wanted on the filesystem.
-.Pp
-When this facility is enabled,
-.Nm mmspawnd
-uses
-.Xr flock 2
-to obtain an exclusive advisory lock on that file whenever one or more
-connections exist, still being served by the service. This means that
-whenever another application is allowed to obtain the lock using the
-same manner (it should also use exclusive mode), no clients are connected
-anymore to the service, and the other application may be allowed to safely
-perform special operations which requires the service to be busy. For as long
-as the file remains locked by the third party application, the
-.Nm mmspawnd
-server will refuse connections from any users (it will in fact accept them
-but immediately drop the connection without running the service). As soon
-as the other application releases back the lock, normal operation is resumed.
-.Pp
-.Xr mmanoncvs 8
-for instance uses this feature during the short amount of time required for
-two rename(2) operations to update the public cvs pserver read-only repository.
-It is very important to make sure that permissions are properly set on the
-lock file when using this feature, to only enable the wanted application to
-obtain the lock (which requires at least read access to the file). See
-the few next options to do this.
-.It Nm ALOCK_USER Ar "user"
-When the
-.Nm ALOCK_PATH
-is set, enabling the alock feature, this specifies the user which should be
-set to be the owner of the lock file.
-.It Nm ALOCK_GROUP Ar "group"
-When the alock feature is enabled, tells which group should be set for the lock
-file.
-.It Nm ALOCK_MODE Ar "mode"
-To be used when the alock feature is enabled. Specifies the permission mode
-bits to apply to the lock file, so that only the intended application can use
-it.
-.It Nm USER Ar "user"
-At server initialization, it drops privileges from the superuser to the
-specified user, definitively. This can be specified as either a username
-or it's user ID number.
-.It Nm GROUPS Ar "group,..."
-When dropping privileges, the process will become part of these groups.
-More than one group may be specified, by name or ID, separated by commas,
-without spaces. The first group will be set to the real process group, and
-others as secondary access ones.
-.It Nm LOG_FACILITY Ar "facility"
-Syslog facility which should be used for error logging. Should normally be
-one of
-.Dv LOG_AUTH , LOG_AUTHPRIV , LOG_CRON,  LOG_DAEMON ,
-.Dv LOG_FTP , LOG_KERN , LOG_LPR , LOG_MAIL ,
-.Dv LOG_NEWS , LOG_SYSLOG , LOG_USER
-or
-.Dv LOG_UUCP .
-See
-.Xr syslog 3
-man page for more information.
-.It Nm COMMAND Ar "command"
-Specifies the command which should be executed for each client which will
-be served. There can be as many command line arguments as
-.Nm MAX_ARGUMENTS
-allows. The path to the executable to launch should be absolute. No globbing
-or substitution of any kind is done on the arguments. It is allowed to
-delimit arguments containing spaces or tabs into single quotes (').
-.It Nm MAX_ARGUMENTS Ar "number"
-This parameter sets the maximum allowed number of command line parameters which
-can be passed to the application in
-.Sy COMMAND .
-.It Nm PROCTITLE Ar "string"
-This is useful if multiple services are served using
-.Xr mmspawnd 8
-for commands such as
-.Xr ps 1 ,
-notably on BSD systems. Where available, this causes the supplied string
-to prefix the comments attached to the processes using
-.Xr setproctitle 3 .
-It also is appended to the daemon name for
-.Xr syslog 3
-at
-.Xr openlog 3
-time.
-.El
-.Ss TCP server administration
-.Bl -tag -width indent -offset indent
-.It Nm LISTEN_ADDRESSES Ar "address ..."
-Tells to which interfaces the server should listen to, separated by spaces.
-The arguments should be enclosed in double quotes if more than one address
-is supplied. These addresses are used for
-.Xr bind 2 .
-Specifying "0.0.0.0" causes
-.Nm mmspawnd
-to listen to all interfaces.
-.It Nm LISTEN_PORT Ar "number"
-Supplies which TCP port number to listen to. This must be a numeric port number
-within the range of 1 to 65535.
-.It Nm MAX_CONNECTIONS Ar "number"
-The maximum number of simultaneous clients which should be served at once.
-.It Nm MAX_ADDRESSES Ar "number"
-The maximum number of simultaneous different client IP addresses to serve.
-.It Nm MAX_PER_ADDRESS Ar "number"
-The maximum number of simultaneous clients to serve at once per IP address.
-.It Nm CONNECTION_RATE Ar "number"
-The maximum number of connections to accept from each address within
-.Nm CONNECTION_PERIOD .
-Can be 0 to disable connection rate throttling.
-.It Nm CONNECTION_PERIOD Ar "number"
-If
-.Nm CONNECTION_RATE
-is non-zero, specifies the number of seconds during which a maximum of
-.Nm CONNECTION_RATE
-connections are to be allowed.
-.It Nm RESOLVE_ADDRESSES Ar "boolean"
-Specifies weither client addresses should be resolved to hostnames when
-logging the connection event via
-.Xr syslog 3 .
-An internal cache is maintained for recently connected addresses for faster
-performance. This is done in the child serving process so that it does not
-slow down the listener process responsible for accepting new connections.
-Should be TRUE or FALSE.
-.El
-.Ss Application security limits
-.Bl -tag -width indent -offset indent
-.It Nm COMMAND_TIMEOUT Ar "seconds"
-Specifies the maximum number of seconds allowed for complete execution of
-.Nm COMMAND .
-If the command does not terminate before this number of seconds elapse, it
-is forcefully killed using the
-.Dv SIGTERM
-signal. Beware to put this limit high enough so that it does not interfere
-with normal service operation. This feature however allows to get rid of
-eternally idle or frozen sessions.
-.Pp
-Eventually, support for network inactivity timeout, as well as bandwidth
-shaping/throttling will be added. However, since those require a new design
-and a rewrite of
-.Xr mmspawnd 8 ,
-this is the best we can do for now. (This behavior is still better than
-.Xr inetd 8 ,
-however). We also ensure to set the
-.Dv SO_KEEPALIVE
-option on the client descriptors to better recognize connection problems and
-act accordingly to stop the process.
-.It Nm RLIMITS Ar "boolean"
-If TRUE, all following
-.Nm RLIMIT_*
-parameters will be applied to the children processes before launching the
-application command if they are not set to -1 values.
-.Xr setrlimit 2
-is called to perform this. Note that these should be set to sane values
-for proper function, by a competent administrator, if this option is
-enabled. When disabled, or if enabled but for each following option specified
-with -1, the defaults are used, which are inherited from the server process.
-.Bl -tag -width indent -offset indent
-.It Nm RLIMIT_CORE Ar "value"
-If not -1, the largest size (in bytes) core file that may be created.
-.It Nm RLIMIT_CPU Ar "value"
-If not -1, The maximum amount of cpu time (in seconds) to be used by
-each process.
-.It Nm RLIMIT_DATA Ar "value"
--1 or The maximum size (in bytes) of the data segment for a process;
-this defines how far a program may extend its break with the
-.Xr sbrk 2
-or
-.Xr mmap 2
-system calls.
-.It Nm RLIMIT_FSIZE Ar "value"
-The largest size (in bytes) file that may be created, or -1.
-.It Nm RLIMIT_MEMLOCK Ar "value"
-The maximum size (in bytes) which a process may lock into physical memory
-(wire) using the
-.Xr mlock 2
-system call function, or -1.
-.It Nm RLIMIT_NOFILE Ar "value"
-If not -1, the maximum number of open files for this process.
-.It Nm RLIMIT_NPROC Ar "value"
-The maximum number of simultaneous processes for this user ID, or -1.
-.It Nm RLIMIT_RSS Ar "value"
-The maximum size (in bytes) to which a process's resident
-set size may grow.  This imposes a limit on the amount of
-physical memory to be given to a process; if memory is
-tight, the system will prefer to take memory from processes
-that are exceeding their declared resident set size.
--1 to use the defaults.
-.It Nm RLIMIT_STACK Ar "value"
-If not -1, the maximum size (in bytes) of the stack segment for a
-process; this defines how far a program's stack segment
-may be extended.  Stack extension is performed automatically by the system.
-.El
-.El
-.Ss Debugging support
-.Bl -tag -width indent -offset indent
-.It Nm STDERR_FILE Ar "fullpath"
-By default, the standard error stream (stderr) of
-.Nm COMMAND
-is redirected to the "/dev/null" device. However, it may be nice to be able
-to obtain those messages from time to time, or to see if any are generated
-by the application. This option, if non-empty, creates, or appends to the
-specified file (outside of the chroot setup). This option should not be
-used on production systems, as the file will grow without bounds. If a log
-rotation system is used,
-.Xr mmspawnd 8
-will require to be restarted everytime it is ran. It is merely for debugging.
-.El
-.Sh DEFAULTS
-The following defaults are used:
-.Pp
-.Bd -literal -offset indent
-CHROOT_DIR             ""
-LOCK_PATH              "/var/run/mmspawnd.lock"
-PID_PATH               "/var/run/mmspawnd.pid"
-ALOCK_PATH             ""
-ALOCK_USER             "mmspawnd"
-ALOCK_GROUP            "mmspawnd"
-ALOCK_MODE             "400"
-USER                   "mmspawnd"
-GROUPS                 "mmspawnd"
-LOG_FACILITY           "LOG_AUTHPRIV"
-COMMAND                        "/sbin/nologin"
-MAX_ARGUMENTS          16
-PROCTITLE              ""
-
-LISTEN_ADDRESSES       "127.0.0.1"
-LISTEN_PORT            2323
-MAX_CONNECTIONS                32
-MAX_ADDRESSES          32
-MAX_PER_ADDRESS                1
-CONNECTION_RATE                5
-CONNECTION_PERIOD      30
-RESOLVE_ADDRESSES      FALSE
-
-COMMAND_TIMEOUT                300
-RLIMITS                        FALSE
-RLIMIT_CORE            -1
-RLIMIT_CPU             -1
-RLIMIT_DATA            -1
-RLIMIT_FSIZE           -1
-RLIMIT_MEMLOCK         -1
-RLIMIT_NOFILE          -1
-RLIMIT_NPROC           -1
-RLIMIT_RSS             -1
-RLIMIT_STACK           -1
-
-STDERR_FILE            ""
-.Ed
-.Sh AUTHOR
-.Nm mmspawnd
-was written by Matthew Mondor, and is
-Copyright (c) 2003, Matthew Mondor, All rights reserved.
-.Sh FILES
-.Bl -tag -width indent -offset indent
-.It Pa /usr/local/etc/mmspawnd.conf
-This file
-.It Pa /usr/local/sbin/mmspawnd
-The
-.Xr mmspawnd 8
-server binary itself.
-.El
-.Sh SEE ALSO
-.Xr mmspawnd 8 ,
-.Xr syslog 3 ,
-.Xr openlog 3 ,
-.Xr chroot 2 ,
-.Xr bind 2 ,
-.Xr setrlimit 2 ,
-.Xr ps 1 ,
-.Xr setproctitle 3 .
-.Sh BUGS
-Not really a bug, but tied to each interface could be most connection control
-options.
-.Pp
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/mmspawnd/new/GNUmakefile b/mmsoftware/mmspawnd/new/GNUmakefile
deleted file mode 100644 (file)
index 89defbf..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-# $Id: GNUmakefile,v 1.1 2003/11/02 22:16:23 mmondor Exp $
-
-all: mmspawnd
-
-%.o: %.c
-       cc -c ${CFLAGS} -I../mmlib -o $@ $<
-
-mmspawnd: mmspawnd.o
-       cc -o $@ $< -lc ../mmlib/libmmondor.a
-
-install: all
-       install -crs -o 0 -g 0 -m 500 mmspawnd /usr/local/sbin
-       install -cr -o 0 -g 0 -m 444 mmspawnd.conf.5 /usr/local/man/man5
-       install -cr -o 0 -g 0 -m 444 mmspawnd.8 /usr/local/man/man8
-
-clean:
-       rm -f mmspawnd mmspawnd.o
diff --git a/mmsoftware/mmspawnd/new/README b/mmsoftware/mmspawnd/new/README
deleted file mode 100644 (file)
index ed8b37d..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-We want to be able to perform the following:
-
-Parent handles incomming connections, maintaining limits, etc. It also
-maintains a pool of processes. It dispatches incomming connections to
-those, distributing them among them. It however must be able to know
-when a connection ended from those processes, so that it may update
-limits, and the hostname/rate per address cache... And it must be able
-to start or kill such processes of the pool as required.
-
-Each of the child processes would need to be able to accept new ones
-to dispatch, at which point it should fork(2), execve(2) etc a-la popen.
-It must also be able to forward data between each of the active connections
-and their particular serving process. For this, it would maintain a poll
-array, as well as an index to tie both sockets together for each, and
-a buffer for EAGAIN when writing. Each of these processes also should
-help the parent master process to account when a connection is dropped.
-When forwarding between the filedescriptors for each client, it should
-also hold statistics to be able to perform bandwidth shaping. This implies
-that it is important to be able to remove wanted filedescriptors from the
-select()/poll() set, at least until the end of the current second elapsed,
-at which point they have to be re-incorporated into the set. When master
-global bandwidth limits are reached, it must be able to only handle new
-connections, and disconnection events, but to otherwise ignore all of them
-until the current second elapses.
-
-I need a generic library to add and remove elements from an array. The
-array must be able to grow and shrink as necessary, upto the maximum allowed
-limit (and thus can be pre-allocated of fixed size). When removing an element,
-it has to shrink the virtual size (it can reorder elements as required so that
-the last element always be the one to remove). When adding, it would simply
-add at the end of the elements, and update the number of current elements
-counter. Hmm this probably means that if we want to refer to an element
-efficiently, we must refer it by index offset rather than run the list to
-locate them. We could probably do those operations while running the list
-for occurred events after poll().
-
-We should only poll for read events, and then attempt to forward. We then
-should account for EAGAIN, writing in non-blocking mode. If this event occurs,
-we need to keep the data to forward in the buffer, to remove both
-filedescriptors for that client from the poll set, continue with other events,
-then go to the next poll round. After a poll round, non-commited buffers would
-pass a next flush attempt, which if succeeds, causes the filedescriptors to
-be reincorporated into the set. This would be done in both directions.
-An index would efficiently match every filedescriptor to their companion one.
-This index would only be updated at new connection or connection loss event.
-
-To make things more efficient, client nodes for which flushing is required
-would be inserted into a temporary linked list, which would be processed
-after poll return. Those which can successfully be flushed will be unlinked
-from that list. Of course, on another error than EAGAIN, the client would
-be discarded.
-
-struct client_node {
-       pnode_t node;
-       pid_t pid;              /* -1 if SIGCHLD was received already */
-       int connection_id;      /* For master process to link? */
-       int pfd, cfd;
-       size_t bytes;           /* Number of bytes in buffer */
-       unsigned char buf[4096];
-};
-
-Instead of connecting the int/fd based index to another int/fd directly, we
-could redirect it to the client_node pointer also. We would store an array
-of the following structure, and index it with [] for access:
-
-struct fd_index {
-       int fd;                         /* Corresponding fd */
-       int pollidx;                    /* Index in poll set */
-       struct client_node *cnode;      /* And node */
-};
-
-Note that the filedescriptor used for communication with the master parent
-connection dispatcher would be treated especially, would be the first in the
-poll set, and would never be removed from it. When global bandwidth limits
-occur, only that fd would be polled (using 1 as nfds_t argument to poll(2)),
-until the remaining of the second elapsed.
-
-Hmm a possible problem is that there would be many filedescriptors to close
-by the other process before execve(2) can safely be done, because two of them
-would be used per client being served by the current server process. We could
-perhaps use close-on-exec flag.
-fcntl(fd, F_SETFD, 1); Of course, we would if required remove the close-on-exec
-flag from some descriptors when necessary, perhaps. We would make sure that
-the process to run the executable has stderr redirected to /dev/null, that
-It's stdin and stdout be redirected to the wanted socket, which would be
-kept open, and that all other filedescriptors be closed.
-
-For bandwidth shaping, the filedescriptors not to poll anymore until a specific
-timeout would also have their client_node moved to another linked list,
-possibly.
-
-
-I should also think about how the pool of server processes will be maintained.
-It would be nice if it could distribute the connections among them based on
-real process load rather than number of connections... For that, it possibly
-could broadcast a request to the processes, and see which one responds the
-first (or use some kind of lock, so that the first one which can get it does).
-In the first case, it of course would ensure to ignore responses for obsolete
-requests (which will come in late). It should be able to detect when to start
-new processes, and also when to start killing some of them which did not serve
-any request for some time. A statistics system similar to when to free pool_t
-pages back could be used, perhaps?
-
-Also, it is yet to be decided if the filedescriptor of the new connection
-should be passed to the processes of the pool, or if they should be allowed
-to accept(2) on a common filedescriptor... If we pass it along, we should
-make sure to only close it after getting the first acknowledgement from one
-of the processes of the pool, obviously. Also, the master process should still
-be able to process further accept(2) and queue the request/fd until it be
-dispatched, and be able to poll(2) both the bound sockets and descriptors
-of each pool. It possibly also could time how much delay was necessary to
-obtain a response from a process of the pool, as a clue on when to start a
-new process, perhaps (but it might be better for the pool members to be able
-to send load stats via the response, which could be taken into account
-via statistics, etc). They could report how much bytes they transfered perhaps,
-since last request or such. Check if linux has decent getrusage(2) also...
-
-It would be impossible to respect the KILL_CHILDREN = NO configuration
-directive anymore, because our processes would be critical to their execution.
-
-Now also think about how the name resolving should be done, and cache
-maintained.
diff --git a/mmsoftware/mmspawnd/new/mmspawnd.c b/mmsoftware/mmspawnd/new/mmspawnd.c
deleted file mode 100644 (file)
index 79a9721..0000000
+++ /dev/null
@@ -1,1498 +0,0 @@
-/* $Id: mmspawnd.c,v 1.2 2004/06/04 01:02:34 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * An inetd-like network server, but which only listens to one port and
- * launches one command. It however performs alot more sanity checking,
- * and has support for chroot(2), custom limits, and setrlimit(2) ones
- * (for the children only, since we handle our own limits checking).
- * To use it for several services, a separate configuration file should
- * be provided for each.
- */
-
-/* TODO:
- * - It would be nice to have all I/O of all client processes be tunnelled
- *   through a bandwidth shaper process (which could then use mmfd(3)).
- *   However, this is not an immediate concern.
- * - Although we cannot monitor if a child process is idle properly using
- *   the current method, it would be nice to have a maximum time to live
- *   parameter in seconds.
- * - The first and second problems could both be solved if we implemented
- *   a popen()-like system instead of having the children serve directly
- *   the socket. We either could have another dedicated process handle the
- *   I/O of many ongoing connections, or to have the main system use it
- *   while still verifying for connection events. Doing this would both
- *   allow custom bandwidth shaping, as well as real network inactivity
- *   monitoring. If using such a method, it would probably be nice to use
- *   a library like libevent or libio which could take adventage of features
- *   like kqueue and epoll where available. Using poll(2) wouldn't be too
- *   bad however...
- */
-
-
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/poll.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <signal.h>
-#include <time.h>
-#include <syslog.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>    /* strerror(3) */
-
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-#include <sys/socket.h> 
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-
-/* For more information about these, see the manual pages in mmlib/ */
-#include <mmtypes.h>
-#include <mmstring.h>
-#include <mmreadcfg.h>
-#include <mmlist.h>
-#include <mmpool.h>
-#include <mmhash.h>
-#include <mmlog.h>
-#include <mmheap.h>
-#include <mmlimitrate.h>
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2003\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmspawnd.c,v 1.2 2004/06/04 01:02:34 mmondor Exp $");
-
-
-
-/* DEFINITIONS */
-
-#define DAEMON_NAME            "mmspawnd"
-#define DAEMON_VERSION         "0.0.1/mmondor"
-
-struct configuration {
-    char CHROOT_DIR[256], LOCK_PATH[256], PID_PATH[256],
-       USER[32], GROUPS[256], LOG_FACILITY[32], LISTEN_ADDRESSES[1024],
-       COMMAND[256], ALOCK_PATH[256], ALOCK_USER[32], ALOCK_GROUP[32],
-       ALOCK_MODE[4];
-    long LISTEN_PORT, MAX_CONNECTIONS, MAX_ADDRESSES, MAX_PER_ADDRESS,
-       CONNECTION_RATE, CONNECTION_PERIOD, MAX_ARGUMENTS, LIMIT_CORE,
-       LIMIT_CPU, LIMIT_DATA, LIMIT_FSIZE, LIMIT_MEMLOCK, LIMIT_NOFILE,
-       LIMIT_NPROC, LIMIT_RSS, LIMIT_STACK;
-    bool RESOLVE_ADDRESSES, RLIMITS;
-};
-
-/* Necessary synchronization locks for shared memory access */
-enum shlocks {
-    SHLOCK_IPADDR = 0,
-    SHLOCK_MAX
-};
-
-/* Base to shared memory, significant both in the parent and children
- * processes. The associated synchronization lock is commented.
- */
-struct shmem_data {
-    /* Locked with SHLOCK_IPADDR */
-    pool_t ipaddr_pool;
-    hashtable_t ipaddr_table;
-};
-
-/* Base to client-specific data, only significant for each children process */
-struct client_data {
-    struct ipaddr_node *ipn;
-    const char *ipaddr;
-    struct sockaddr saddr;
-};
-
-/* And server-specific data */
-struct server_data {
-    int runlock, alock, current_connections;
-    pool_t pid_pool;
-    hashtable_t pid_table;
-    char *line, *command, **argv;
-    rlim_t *rlimits;
-};
-
-/* Defines an interface to listen to */
-struct iface {
-    char address[16];          /* Server address string or '\0' */
-    int sock;                  /* Bound socket (or -1) */
-    struct sockaddr_in saddr;  /* Address to bind(2) to */
-};
-
-/* Used for the hostname cache and per-address connection rate limiting */
-struct ipaddr_node {
-    hashnode_t node;
-    struct limitrate lr;
-    struct sockaddr address;   /* Key */
-    long connections;
-    char hostname[64];
-};
-
-/* Used to efficiently link a child pid_t to an ipaddr_node structure pointer,
- * so that we may easily decrease the total connections counter for that
- * address in our SIGCHLD handler.
- */
-struct pid_node {
-    hashnode_t node;
-    pid_t pid;                 /* Key */
-    struct ipaddr_node *ipn;
-};
-
-/* Used to store shared context between ipddr_expire_process() and it's
- * iterator function
- */
-struct ipaddr_expire_process_iterator_udata {
-    time_t current, soonest;
-};
-
-/* Useful macro to cleanup code later */
-#define SETRLIMIT(restxt, resource, limit) do { \
-    if ((limit) != -1) { \
-       struct rlimit rl; \
-       \
-       rl.rlim_cur = rl.rlim_max = (rlim_t)(limit); \
-       if (setrlimit((resource), &rl) == -1) \
-           syslog(LOG_NOTICE, "* setrlimit(%s, %ld) - (%s)", \
-                   (restxt), (limit), strerror(errno)); \
-    } \
-} while (/* CONSTCOND */0) ;
-
-/* Internal mappings for the rlimits in the array */
-enum rlimit {
-    RL_CORE = 0,
-    RL_CPU,
-    RL_DATA,
-    RL_FSIZE,
-    RL_MEMLOCK,
-    RL_NOFILE,
-    RL_NPROC,
-    RL_RSS,
-    RL_STACK
-}
-
-
-
-/* PROTOTYPES */
-
-int main(int, char **);
-
-static bool daemon_detach(const char *, const char *);
-static void daemon_sighandler(int);
-static bool client_kill_iterator(hashnode_t *, void *);
-static void pidfile_write(const char *);
-static int lock_check(const char *);
-static struct iface *ifaces_parse(char *);
-
-static void client_resolve(void);
-static bool exec_popen(int *, pid_t *, const char *, char * const *, rlim_t *,
-       struct iface *, int, struct ipaddr_node *, struct sockaddr *,
-       const char *);
-static void exec_command(const char *, char * const *, rlim_t *);
-
-static bool connection_open(const char *);
-static void connection_close(void);
-static struct ipaddr_node *ipaddr_open(struct sockaddr *, const char *);
-static void ipaddr_close(struct ipaddr_node *);
-
-static u_int32_t key_hash32(const void *, size_t);
-static int key_cmp32(const void *, const void *, size_t);
-static int key_pidcmp(const void *, const void *, size_t);
-static u_int32_t key_pidhash(const void *, size_t);
-
-static pid_t launch_ipaddr_expire_process(uid_t, gid_t *, int);
-static void ipaddr_expire_process(void);
-static bool ipaddr_expire_process_iterator(hashnode_t *, void *);
-
-
-
-/* GLOBALS */
-
-/* Normal static data used for current configuration, so that clients may keep
- * their active config copy in case the server reloads it; Also is of faster
- * access than shared memory, requireing no locking for synchronization.
- */
-static struct configuration CONF;
-
-/* Base structure to all shared memory data, for which synchronization is
- * required using locks.
- */
-static struct shmem_data *shmem = NULL;
-
-/* Static data array mapping lock files descriptors to an index used with
- * flock(3) for the various shared memory sections.
- */
-static int locks[(enum shlocks)SHLOCK_MAX];
-
-/* Static client-specific data which is only significant for each children
- * process, as well as server-specific data which belongs to the listener
- * process.
- */
-static struct client_data client;
-static struct server_data server;
-rlim_t rlimits[9];
-
-
-
-/* CODE */
-
-int main(int argc, char **argv)
-{
-    char *conf_file = "/usr/local/etc/mmspawnd.conf";
-    pid_t uid;
-    gid_t *gids;
-    int ngids, backlog;
-    long facility;
-    cres_t cres;
-    carg_t *cargp;
-    carg_t cargs[] = {
-       {CAT_STR, CAF_NONE, 0, 255, "CHROOT_DIR", CONF.CHROOT_DIR},
-       {CAT_STR, CAF_NONE, 1, 255, "LOCK_PATH", CONF.LOCK_PATH},
-       {CAT_STR, CAF_NONE, 1, 255, "PID_PATH", CONF.PID_PATH},
-       {CAT_STR, CAF_NONE, 1, 31, "USER", CONF.USER},
-       {CAT_STR, CAF_NONE, 1, 255, "GROUPS", CONF.GROUPS},
-       {CAT_STR, CAF_NONE, 1, 31, "LOG_FACILITY", CONF.LOG_FACILITY},
-       {CAT_STR, CAF_NONE, 1, 1023, "LISTEN_ADDRESSES",
-           CONF.LISTEN_ADDRESSES},
-       {CAT_STR, CAF_NONE, 1, 255, "COMMAND", CONF.COMMAND},
-       {CAT_STR, CAF_NONE, 0, 255, "ALOCK_PATH", CONF.ALOCK_PATH},
-       {CAT_STR, CAF_NONE, 1, 32, "ALOCK_USER", CONF.ALOCK_USER},
-       {CAT_STR, CAF_NONE, 1, 32, "ALOCK_GROUP", CONF.ALOCK_GROUP},
-       {CAT_STR, CAF_NONE, 1, 32, "ALOCK_MODE", CONF.ALOCK_MODE},
-       {CAT_VAL, CAF_NONE, 0, 64, "MAX_ARGUMENTS", &CONF.MAX_ARGUMENTS},
-       {CAT_VAL, CAF_NONE, 1, 65535, "LISTEN_PORT", &CONF.LISTEN_PORT},
-       {CAT_VAL, CAF_NONE, 1, 99999, "MAX_CONNECTIONS",
-           &CONF.MAX_CONNECTIONS},
-       {CAT_VAL, CAF_NONE, 1, 99999, "MAX_ADDRESSES", &CONF.MAX_ADDRESSES},
-       {CAT_VAL, CAF_NONE, 1, 99999, "MAX_PER_ADDRESS",
-           &CONF.MAX_PER_ADDRESS},
-       {CAT_VAL, CAF_NONE, 0, 99999, "CONNECTION_RATE",
-           &CONF.CONNECTION_RATE},
-       {CAT_VAL, CAF_NONE, 0, 99999, "CONNECTION_PERIOD",
-           &CONF.CONNECTION_PERIOD},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_CORE", &CONF.LIMIT_CORE},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_CPU", &CONF.LIMIT_CPU},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_DATA", &CONF.LIMIT_DATA},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_FSIZE", &CONF.LIMIT_FSIZE},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_MEMLOCK", &CONF.LIMIT_MEMLOCK},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_NOFILE", &CONF.LIMIT_NOFILE},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_NPROC", &CONF.LIMIT_NPROC},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_RSS", &CONF.LIMIT_RSS},
-       {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_STACK", &CONF.LIMIT_STACK},
-       {CAT_BOOL, CAF_NONE, 0, 0, "RESOLVE_ADDRESSES",
-           &CONF.RESOLVE_ADDRESSES},
-       {CAT_BOOL, CAF_NONE, 0, 0, "KILL_CHILDREN", &CONF.KILL_CHILDREN},
-       {CAT_BOOL, CAF_NONE, 0, 0, "RLIMITS", &CONF.RLIMITS},
-       {CAT_END, CAF_NONE, 0, 0, NULL, NULL}
-    };
-    cmap_t cmap[] = {
-       {"LOG_AUTH", LOG_AUTH},
-       {"LOG_AUTHPRIV", LOG_AUTHPRIV},
-       {"LOG_CRON", LOG_CRON},
-       {"LOG_DAEMON", LOG_DAEMON},
-       {"LOG_FTP", LOG_FTP},
-       {"LOG_LPR", LOG_LPR},
-       {"LOG_MAIL", LOG_MAIL},
-       {"LOG_NEWS", LOG_NEWS},
-       {"LOG_SYSLOG", LOG_SYSLOG},
-       {"LOG_USER", LOG_USER},
-       {"LOG_UUCP", LOG_UUCP},
-       {NULL, 0}
-    };
-    int i, nifaces;
-    struct sockaddr_in server_addr;
-    struct iface *ifaces, *tif;
-    struct pollfd *fds;
-
-    /* Set harmless defaults */
-    *CONF.CHROOT_DIR = '\0';
-    (void) mm_strcpy(CONF.LOCK_PATH, "/var/run/mmspawnd.lock");
-    (void) mm_strcpy(CONF.PID_PATH, "/var/run/mmspawnd.pid");
-    (void) mm_strcpy(CONF.USER, "mmspawnd");
-    (void) mm_strcpy(CONF.GROUPS, "mmspawnd");
-    (void) mm_strcpy(CONF.LOG_FACILITY, "LOG_AUTHPRIV");
-    (void) mm_strcpy(CONF.LISTEN_ADDRESSES, "127.0.0.1");
-    (void) mm_strcpy(CONF.COMMAND, "/sbin/nologin");
-    *CONF.ALOCK_PATH = '\0';
-    (void) mm_strcpy(CONF.ALOCK_USER, "mmspawnd");
-    (void) mm_strcpy(CONF.ALOCK_GROUP, "mmspawnd");
-    (void) mm_strcpy(CONF.ALOCK_MODE, "400");
-    CONF.LISTEN_PORT = 2323;
-    CONF.MAX_CONNECTIONS = 32;
-    CONF.MAX_ADDRESSES = 32;
-    CONF.MAX_PER_ADDRESS = 1;
-    CONF.CONNECTION_RATE = 5;
-    CONF.CONNECTION_PERIOD = 30;
-    CONF.MAX_ARGUMENTS = 16;
-    CONF.LIMIT_CORE = -1;
-    CONF.LIMIT_CPU = -1;
-    CONF.LIMIT_DATA = -1;
-    CONF.LIMIT_FSIZE = -1;
-    CONF.LIMIT_MEMLOCK = -1;
-    CONF.LIMIT_NOFILE = -1;
-    CONF.LIMIT_NPROC = -1;
-    CONF.LIMIT_RSS = -1;
-    CONF.LIMIT_STACK = -1;
-    CONF.RESOLVE_ADDRESSES = FALSE;
-    CONF.KILL_CHILDREN = TRUE;
-    CONF.RLIMITS = FALSE;
-
-    /* Read config file */
-    if (argc == 2)
-       conf_file = argv[1];
-    if (!mmreadcfg(&cres, cargs, conf_file)) {
-       /* Error parsing configuration file, report which */
-       (void) fprintf(stderr, "\nError parsing '%s'\n", conf_file);
-       (void) fprintf(stderr, "Error  : %s\n", mmreadcfg_strerr(cres.CR_Err));
-       if (*(cres.CR_Data))
-           (void) fprintf(stderr, "Data   : %s\n", cres.CR_Data);
-       if ((cargp = cres.CR_Keyword) != NULL) {
-           (void) fprintf(stderr, "Keyword: %s\n", cargp->CA_Keyword);
-           (void) fprintf(stderr, "Minimum: %ld\n", cargp->CA_Min);
-           (void) fprintf(stderr, "Maximum: %ld\n", cargp->CA_Max);
-       }
-       if (cres.CR_Line != -1)
-           (void) fprintf(stderr, "Line   : %d\n", cres.CR_Line);
-       (void) fprintf(stderr, "\n");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Post parsing */
-    if (!mmmapstring(cmap, CONF.LOG_FACILITY, &facility)) {
-       (void) fprintf(stderr, "\nUnknown syslog facility %s\n\n",
-                      CONF.LOG_FACILITY);
-       exit(EXIT_FAILURE);
-    }
-    if ((uid = mmgetuid(CONF.USER)) == -1) {
-       (void) fprintf(stderr, "\nUnknown USER '%s'\n\n", CONF.USER);
-       exit(EXIT_FAILURE);
-    }
-    if (!(gids = mmgetgidarray(&ngids, CONF.GROUPS))) {
-       (void) fprintf(stderr, "\nOne of following GROUPS unknown: '%s'\n\n",
-                      CONF.GROUPS);
-       exit(EXIT_FAILURE);
-    }
-    if (*CONF.ALOCK_PATH != '\0') {
-       uid_t u;
-       gid_t g;
-       mode_t m;
-
-       if ((u = mmgetuid(CONF.ALOCK_USER)) == -1) {
-           (void) fprintf(stderr, "\nUnknown ALOCK_USER '%s'\n\n",
-                          CONF.ALOCK_USER);
-           exit(EXIT_FAILURE);
-       }
-       if ((g = mmgetgid(CONF.ALOCK_GROUP)) == -1) {
-           (void) fprintf(stderr, "\nUnknown ALOCK_GROUP '%s'\n\n",
-                          CONF.ALOCK_GROUP);
-           exit(EXIT_FAILURE);
-       }
-       sscanf(CONF.ALOCK_MODE, "%o", &m);
-       if (m == 0 || m > 0770) {
-           (void) fprintf(stderr, "\nIllegal ALOCK_MODE '%03o'\n\n", m);
-           exit(EXIT_FAILURE);
-       }
-       if ((server.alock = open(CONF.ALOCK_PATH, O_WRONLY | O_CREAT, m))
-               == -1) {
-           (void) fprintf(stderr, "\n* main() - open(%s) - (%s)\n\n",
-                          CONF.ALOCK_PATH, strerror(errno));
-           exit(EXIT_FAILURE);
-       }
-       if (fchown(server.alock, u, g) == -1) {
-           (void) fprintf(stderr, "\n* main() - fchown(%s) - (%s)\n\n",
-                          CONF.ALOCK_PATH, strerror(errno));
-           exit(EXIT_FAILURE);
-       }
-    } else
-       server.alock = -1;
-    if ((ifaces = ifaces_parse(CONF.LISTEN_ADDRESSES)) == NULL) {
-       (void) fprintf(stderr, "\nInvalid LISTEN_ADDRESSES\n\n");
-       exit(EXIT_FAILURE);
-    }
-    if ((server.line = mm_strdup(CONF.COMMAND)) != NULL && (server.argv =
-               malloc(sizeof(char *) * (CONF.MAX_ARGUMENTS + 2))) != NULL) {
-       int argc;
-
-       if (!mm_cmdparse(&server.command, &argc, server.argv, server.line,
-                   CONF.MAX_ARGUMENTS + 2)) {
-           (void) fprintf(stderr, "\nError parsing COMMAND ",
-                          "(also check MAX_ARGUMENTS)\n\n");
-           exit(EXIT_FAILURE);
-       }
-    } else {
-       (void) fprintf(stderr, "\nOut of memory\n\n");
-       exit(EXIT_FAILURE);
-    }
-    if (CONF.RLIMITS) {
-       rlimits[RL_CORE] = CONF.LIMIT_CORE;
-       rlimits[RL_CPU] = CONF.LIMIT_CPU;
-       rlimits[RL_DATA] = CONF.LIMIT_DATA;
-       rlimits[RL_FSIZE] = CONF.LIMIT_FSIZE;
-       rlimits[RL_MEMLOCK] = CONF.LIMIT_MEMLOCK;
-       rlimits[RL_NOFILE] = CONF.LIMIT_NOFILE;
-       rlimits[RL_NPROC] = CONF.LIMIT_NPROC;
-       rlimits[RL_RSS] = CONF.LIMIT_RSS;
-       rlimits[RL_STACK] = CONF.LIMIT_STACK;
-       server.rlimits = rlimits;
-    } else
-       server.rlimits = NULL;
-
-    /* Config file seemed right, start with initialization */
-    openlog(DAEMON_NAME, LOG_PID | LOG_NDELAY, facility);
-
-    /* Some consistency checks according to permissions */
-#ifndef NODROPPRIVS
-    if ((getuid())) {
-       (void) fprintf(stderr,
-                      "\nOnly the super user may start this daemon\n\n");
-       syslog(LOG_NOTICE,
-               "main() - Refused to launch for uid %d attempt (not root, \
-!NODROPPRIVS)", (int)getuid());
-       exit(EXIT_FAILURE);
-    }
-#else /* NODROPPRIVS */
-    if ((getuid()) == 0) {
-       (void) fprintf(stderr, "\nCompiled with NODROPPRIVS, ",
-                      "refusing to run as uid 0\n\n");
-       syslog(LOG_NOTICE, "main() - NODROPPRIVS, refusing to run as uid 0");
-       exit(EXIT_FAILURE);
-    }
-#endif /* !NODROPPRIVS */
-
-    /* Make sure that only one instance is running */
-    if ((server.runlock = lock_check(CONF.LOCK_PATH)) == -1) {
-       (void) fprintf(stderr, "\n%s already running\n\n", DAEMON_NAME);
-       syslog(LOG_NOTICE, "main() - %s already running", DAEMON_NAME);
-       exit(EXIT_FAILURE);
-    }
-
-    /* Things we want to do now in case we chroot(2) */
-    /* XXX If we want to use mmstat(3)/mmstatd(8) we should initialize the
-     * system here. However, this is a problem with mmstat(3) and chroot
-     * setups, unless an mmstatd(8) daemon runs into the chroot itself,
-     * or that it is certain to not be restarted.
-     * I should fix mmstatd(8) to support chroot(2).
-     */
-
-    /* Create our locks for shared memory synchronization */
-    if (!shlocks_init(CONF.LOCK_PATH, locks, SHLOCK_MAX)) {
-       syslog(LOG_NOTICE, "main() - shlocks_init()");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Close unnecessary filedescriptors and become a daemon, chroot(2)ing
-     * if necessary. This also sets up the connection listener signal handlers.
-     */
-    if (!daemon_detach(CONF.PID_PATH, CONF.CHROOT_DIR)) {
-       syslog(LOG_NOTICE, "main() - daemon_detach()");
-       exit(EXIT_FAILURE);
-    }
-
-   /* Reset number of current connections to 0 and initialize the pid_t table
-     * and pool.
-     */
-    server.current_connections = 0;
-    if (!pool_init(&server.pid_pool, malloc, free, sizeof(struct pid_node),
-               CONF.MAX_CONNECTIONS, 1, 1)) {
-       syslog(LOG_NOTICE, "main() - pool_init(pid_pool)");
-       exit(EXIT_FAILURE);
-    }
-    if (!hashtable_init(&server.pid_table, CONF.MAX_CONNECTIONS, 1, malloc,
-               free, key_pidcmp, key_pidhash, FALSE)) {
-       syslog(LOG_NOTICE, "main() - hashtable_init(pid_table)");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Allocate some shared memory */
-    if ((shmem = shmem_malloc(sizeof(struct shmem_data))) == NULL) {
-       syslog(LOG_NOTICE, "main() - shmem_malloc()");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Initialize shared memory pool and table. Note that we make sure to
-     * allocate the memory in a single block, large enough, so that
-     * shmem_free() not be called by another process, which obviously would
-     * only munmap(2) within it's own process.
-     */
-    if (!pool_init(&shmem->ipaddr_pool, shmem_malloc, shmem_free,
-               sizeof(struct ipaddr_node), CONF.MAX_ADDRESSES, 1, 1)) {
-       syslog(LOG_NOTICE, "main() - pool_init(ipaddr_pool)");
-       exit(EXIT_FAILURE);
-    }
-    if (!hashtable_init(&shmem->ipaddr_table, CONF.MAX_ADDRESSES, 1,
-               shmem_malloc, shmem_free, key_cmp32, key_hash32, FALSE)) {
-       syslog(LOG_NOTICE, "main() - hashtable_init(ipaddr_table)");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Start our cache entry expiration process. It would have been possible
-     * to use setitimer(2) and do this into the signal handler of the main
-     * process, alternatively. However, since we already have the interprocess
-     * locking glue setup, we can keep the design simple and use a process.
-     * Further, it allows to have the resolver fill the cache from the child
-     * processes asynchroneously, without causing the main listener to block.
-     * Note that the following function also causes the child to become
-     * unprivileged.
-     */
-    if (launch_ipaddr_expire_process(uid, gids, ngids) < 1) {
-       syslog(LOG_NOTICE, "main() - launch_ipaddr_expire_process()");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Bind our port to the various interfaces */
-    for (nifaces = 0, tif = ifaces; *(tif->address) != '\0'; tif++) {
-       if ((tif->sock = socket(AF_INET, SOCK_STREAM, 0)) > -1) {
-           i = 1;
-           if ((setsockopt(tif->sock, SOL_SOCKET, SO_REUSEADDR, &i,
-                           sizeof(int))) == -1)
-               syslog(LOG_NOTICE,
-                       "main() - setsockopt(SO_REUSEADDR %s:%d)",
-                       tif->address, (int)CONF.LISTEN_PORT);
-           i = 0;
-           mm_memclr(&server_addr, sizeof(struct sockaddr_in));
-           server_addr.sin_family = AF_INET;
-           server_addr.sin_addr = tif->saddr.sin_addr;
-           server_addr.sin_port = htons(CONF.LISTEN_PORT);
-           if ((bind(tif->sock, (struct sockaddr *)(void *)&server_addr,
-                           sizeof(struct sockaddr_in))) == 0)
-               nifaces++;
-           else {
-               syslog(LOG_NOTICE,
-                       "main() - bind(%s:%d)",
-                       tif->address, (int)CONF.LISTEN_PORT);
-               (void) close(tif->sock);
-               tif->sock = -1;
-           }
-       }
-    }
-    if (nifaces == 0) {
-       syslog(LOG_NOTICE, "No interfaces (left) to listen to");
-       (void) kill(0, SIGTERM);
-       exit(EXIT_FAILURE);
-    }
-
-    /* Drop privileges definitively */
-    if (!mmdropprivs(uid, gids, ngids)) {
-       syslog(LOG_NOTICE, "Cannot change uid and gids to safe privs");
-       exit(EXIT_FAILURE);
-    }
-
-#ifndef __GLIBC__
-    setproctitle("Socket listener process");
-#endif /* __GLIBC__ */
-
-    /* Start listening to bound sockets */
-    backlog = CONF.MAX_ADDRESSES * CONF.MAX_PER_ADDRESS;
-    if (backlog > CONF.MAX_CONNECTIONS)
-       backlog = CONF.MAX_CONNECTIONS;
-    for (tif = ifaces; *(tif->address); tif++) {
-       if (tif->sock != -1) {
-           if ((listen(tif->sock, backlog)) == -1) {
-               syslog(LOG_NOTICE, "* main() - listen(%s)", tif->address);
-               (void) close(tif->sock);
-               tif->sock = -1;
-               nifaces--;
-           } else
-               syslog(LOG_NOTICE, "Listening on [%s:%d]",
-                       tif->address, (int)CONF.LISTEN_PORT);
-       }
-    }
-
-    /* Setup our poll() array for the interfaces we'll accept() on */
-    if ((fds = malloc(sizeof(struct pollfd) * nifaces)) != NULL) {
-       for (i = 0, tif = ifaces; *(tif->address) != '\0'; tif++) {
-           if (tif->sock != -1) {
-               fds[i].fd = tif->sock;
-               fds[i].events = POLLIN;
-               fds[i].revents = 0;
-               i++;
-           }
-       }
-    } else {
-       syslog(LOG_NOTICE, "Out of memory");
-       exit(EXIT_FAILURE);
-    }
-
-    /* Listen for connections and dispatch them to independant processes */
-    syslog(LOG_NOTICE, "Launched for uid %d with configuration file '%s', \
-listening for connections on port %d. Service is '%s'.",
-       uid, conf_file, (int)CONF.LISTEN_PORT, CONF.COMMAND);
-    for (;;) {
-       int i, sock, nifaces2;
-       socklen_t addrl = sizeof(struct sockaddr);
-       struct sockaddr addr;
-       struct ipaddr_node *ipn = NULL;
-       char ipaddr[20];
-
-       while ((nifaces2 = poll(fds, nifaces, -1)) == -1 && errno == EINTR) ;
-       for (i = 0; i < nifaces && nifaces2 > 0; i++) {
-           if (fds[i].revents & POLLIN) {
-               nifaces2--;
-               if ((sock = accept(fds[i].fd, &addr, &addrl)) != -1) {
-                   bool connection;
-
-                   /* We got a connection, verify if within allowed limits. */
-                   mm_strcpy(ipaddr, "0.0.0.0");
-                   (void) inet_ntop(AF_INET,
-                           &(((struct sockaddr_in *)&addr)->sin_addr),
-                           ipaddr, 19);
-                   if ((connection = connection_open(ipaddr)) &&
-                           (ipn = ipaddr_open(&addr, ipaddr)) != NULL) {
-                       pid_t pid;
-                       int csock;
-
-                       if (exec_popen(&csock, &pid, server.command,
-                                   (char * const *)server.argv,
-                                   server.rlimits, ifaces, nifaces,
-                                   ipn, &addr, ipaddr)) {
-                           /* Parent, record child process, and continue.
-                            * As we use a preallocated pool of enough nodes
-                            * for the allowed limits, no need for error
-                            * checking at pool_alloc(). We now need to
-                            * perform forwarding from csock to sock back
-                            * and forth, until a socket problem occurs, or
-                            * that an inactivity timeout occurs.
-                            * XXX We probably do not need to handle
-                            * SIGCHLD specially anymore, since the socket
-                            * disconnection or SIGPIPE will now occur at
-                            * child process termination. It also probably
-                            * would be nice to dedicate a process to
-                            * forwarding among those descriptors, perhaps...
-                            * We then could be dedicated to new connections.
-                            * We would need a lock to add new nodes to the
-                            * forwarder process, however. It also would need
-                            * to be able to notify us when a connection is
-                            * dropped (or a child process exited). We probably
-                            * also need to pass it the new client connection
-                            * filedescriptor... If we do not dedicate a
-                            * process for this, we should then make sure to
-                            * always verify the status of the bound sockets
-                            * even when sleeping for bandwidth shaping.
-                            * If we are able to delegate the tasks to other
-                            * processes, it also could make the system more
-                            * scalable. The administrator could specify how
-                            * many processes to run to handle forwarding...
-                            */
-       a                   pnod = (struct pid_node *)pool_alloc(
-                                   &server.pid_pool, FALSE);
-                           pnod->pid = pid;
-                           pnod->ipn = ipn;
-                           (void) hashtable_link(&server.pid_table,
-                                   (hashnode_t *)pnod, &pnod->pid,
-                                   sizeof(pid_t));
-                           /* XXX */
-                       }
-                   } else {
-                       /* Limits have been exceeded, close socket immediately
-                        */
-                       (void) close(sock);
-                       if (connection)
-                           connection_close();
-                       if (ipn != NULL)
-                           ipaddr_close(ipn);
-                   }
-               } else
-                   DEBUG_PRINTF("main", "accept()");
-           }
-       }
-    }
-
-    /* NOTREACHED */
-    exit(EXIT_SUCCESS);
-}
-
-
-/* Uses fork(2) and setsid(2) to become a daemon, and detaches from the
- * current tty. Also calls chroot(2) and chdir(2) if a jail directory is
- * supplied. Returns either successful or not (TRUE, FALSE).
- */
-static bool daemon_detach(const char *pidfile, const char *jail)
-{
-    int pid;
-
-#ifdef NODETACH
-    pid = getpid();
-#else /* NODETACH */
-    if ((pid = fork()) != -1)
-#endif /* !NODETACH */
-    {
-
-#ifndef NODETACH
-       if (pid > 0) {
-           /* Parent */
-           exit(EXIT_SUCCESS);
-       } else
-#endif /* !NODETACH */
-       {
-           int fd;
-           struct sigaction act;
-
-           /* Child */
-           (void) setsid();
-           (void) chdir("/");
-           if ((fd = open("/dev/null", O_RDWR)) != -1) {
-               (void) dup2(fd, 0);
-               (void) dup2(fd, 1);
-               (void) dup2(fd, 2);
-               if (fd > 2)
-                   (void) close(fd);
-           }
-           pidfile_write(pidfile);
-
-           /* Chroot if required */
-           if (jail != NULL && *jail != '\0') {
-               if ((chroot(jail)) == -1) {
-                   syslog(LOG_NOTICE,
-                           "daemon_detach() - Could not chroot(2) to '%s'",
-                           jail);
-                   exit(EXIT_FAILURE);
-               }
-               (void) chdir("/");
-           }
-
-           /* Setup our server signal handlers. We also want to make
-            * sure that we catch SIGCHLD for every process that exits.
-            * (we don't need SIGCHLD events for process STOP however).
-            */
-           act.sa_handler = daemon_sighandler;
-           act.sa_flags = SA_NOCLDSTOP;
-           (void) sigemptyset(&act.sa_mask);
-
-           (void) sigaction(SIGTERM, &act, NULL);
-           (void) sigaction(SIGINT, &act, NULL);
-           (void) sigaction(SIGCHLD, &act, NULL);
-           (void) sigaction(SIGSEGV, &act, NULL);
-
-           act.sa_handler = SIG_IGN;
-           (void) sigaction(SIGTTOU, &act, NULL);
-           (void) sigaction(SIGTTIN, &act, NULL);
-           (void) sigaction(SIGTSTP, &act, NULL);
-           (void) sigaction(SIGPIPE, &act, NULL);
-
-           (void) umask(0);
-
-           return TRUE;
-       }
-    }
-
-    return FALSE;
-}
-
-
-/* This signal handler takes care of wanted signals in the TCP listener
- * server (parent process).
- */
-static void daemon_sighandler(int sig)
-{
-    switch (sig) {
-    case SIGSEGV:
-       syslog(LOG_NOTICE, "Exiting (SIGSEGV!)");
-       goto end;
-       break;
-    case SIGTERM:
-       syslog(LOG_NOTICE, "Exiting (SIGTERM)");
-       goto end;
-       break;
-    case SIGINT:
-       syslog(LOG_NOTICE, "Exiting (SIGINT)");
-       goto end;
-       break;
-    case SIGCHLD:
-       {
-           int status = 0;
-           pid_t pid;
-           struct pid_node *pn;
-
-           while ((pid = wait3(&status, WNOHANG, NULL)) == -1 &&
-                   errno == EINTR) ;
-           if (pid != -1) {
-               bool quit = FALSE;
-
-               if (WIFSIGNALED(status)) {
-                   syslog(LOG_NOTICE, "Child %d received signal %d", (int)pid,
-                           WTERMSIG(status));
-                   quit = TRUE;
-               }
-               if (WIFEXITED(status)) {
-                   if (WEXITSTATUS(status) != 0)
-                       syslog(LOG_NOTICE, "Child %d terminated with code %d",
-                               (int)pid, WEXITSTATUS(status));
-                   else
-                       syslog(LOG_NOTICE, "Child %d terminated normally",
-                               (int)pid);
-                   quit = TRUE;
-               }
-               if (quit) {
-                   /* We have the pid of the process which just exited.
-                    * We must decrease the total connections counter as well
-                    * as the connections counter for that address.
-                    * We must do this here since execve(2) does not return
-                    * on success. We use the hashtable_t we setup to link
-                    * pid_t -> struct ipaddr_node *.
-                    */
-                   if ((pn = (struct pid_node *)hashtable_lookup(
-                                   &server.pid_table, &pid,
-                                   sizeof(pid_t))) != NULL) {
-                       connection_close();
-                       ipaddr_close(pn->ipn);
-                       hashtable_unlink(&server.pid_table, (hashnode_t *)pn);
-                       (void) pool_free((pnode_t *)pn);
-                   }
-               }
-           }
-       }
-       break;
-    }
-
-    return;
-
-end:
-    /* Cleanly exit all processes. Because we use setsid(2) in the children,
-     * We use our table of still active children processes instead of a single
-     * kill(2) on the whole process group. We do that too afterwards so that
-     * we cleanup our server-side processes afterwards.
-     */
-    if (CONF.KILL_CHILDREN)
-       hashtable_iterate(&server.pid_table, client_kill_iterator, NULL);
-    {
-       struct sigaction act;
-
-       act.sa_handler = SIG_IGN;
-       act.sa_flags = SA_NOCLDSTOP;
-       (void) sigemptyset(&act.sa_mask);
-
-       (void) sigaction(SIGTERM, &act, NULL);
-    }
-    (void) kill(0, SIGTERM);
-    shlocks_destroy(CONF.LOCK_PATH, locks, (enum shlocks)SHLOCK_MAX, TRUE);
-    shmem_freeall();
-    exit(EXIT_SUCCESS);
-}
-
-
-/* ARGSUSED */
-static bool client_kill_iterator(hashnode_t *hnod, void *udata)
-{
-    (void) kill(((struct pid_node *)hnod)->pid, SIGTERM);
-
-    return TRUE;
-}
-
-
-/* Writes our process ID number to specified file. To be called before
- * chroot(2) or dropping privileges.
- */
-static void pidfile_write(const char *file)
-{
-    char str[16];
-    int fd;
-
-    if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600)) != -1) {
-       (void) snprintf(str, 15, "%d\n", getpid());
-       (void) write(fd, str, mm_strlen(str));
-       (void) close(fd);
-    } else
-       DEBUG_PRINTF("pidfile_write", "open(%s)", file);
-}
-
-
-/* This uses an fd which remains open in child processes, if they close it the
- * lock is released automatically by the process. Returns -1 if the lock
- * is already held, or a filedescriptor to the lock on success.
- */
-static int lock_check(const char *file)
-{
-    int fd;
-
-    if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600)) != -1) {
-       if ((flock(fd, LOCK_EX | LOCK_NB)) == 0)
-           return fd;
-       (void) close(fd);
-    } else
-       DEBUG_PRINTF("lock_check", "open(%s)", file);
-
-    return -1;
-}
-
-
-/* Simple function to parse the interfaces specified on a line */
-static struct iface *ifaces_parse(char *addresses)
-{
-    struct iface *ifaces;
-    char *ips[65];
-    struct sockaddr_in saddr;
-    int n, i;
-
-    ifaces = NULL;
-
-    if (addresses != NULL && *addresses != '\0') {
-       if ((n = mm_straspl(ips, addresses, 64)) > 0) {
-           if ((ifaces = malloc(sizeof(struct iface) * (n + 1))) != NULL) {
-               /* Setup our array */
-               for (i = 0; i < n; i++) {
-                   mm_memclr(&saddr, sizeof(struct sockaddr_in));
-                   if ((inet_aton(ips[i], &(saddr.sin_addr))) == 1) {
-                       (void) mm_strncpy(ifaces[i].address, ips[i], 15);
-                       ifaces[i].sock = -1;
-                       ifaces[i].saddr = saddr;
-                       *(ifaces[i + 1].address) = '\0';
-                   } else {
-                       syslog(LOG_NOTICE,
-                               "ifaces_parse() - Invalid address [%s]",
-                               ips[i]);
-                       free(ifaces);
-                       ifaces = NULL;
-                       break;
-                   }
-               }
-           }
-       }
-    }
-
-    return ifaces;
-}
-
-
-/* Internal function to resove the hostname of the IP address of a connected
- * client and cache it (if RESOLVE_ADDRESSES was enabled).
- */
-static void client_resolve(void)
-{
-    if (CONF.RESOLVE_ADDRESSES) {
-       if (*client.ipn->hostname == '\0') {
-           if ((flock(locks[SHLOCK_IPADDR], LOCK_EX)) == 0) {
-               if (*client.ipn->hostname == '\0') {
-                   if ((getnameinfo(&client.saddr, sizeof(struct sockaddr_in),
-                                   client.ipn->hostname, 64, NULL, 0, 0))
-                           != 0)
-                       DEBUG_PRINTF("client_resolve", "getnameinfo(%s)",
-                               client.ipaddr);
-               }
-               (void) flock(locks[SHLOCK_IPADDR], LOCK_UN);
-           }
-       }
-       syslog(LOG_NOTICE, "Connection from %s (%s)", client.ipn->hostname,
-               client.ipaddr);
-    } else
-       syslog(LOG_NOTICE, "Connection from %s", client.ipaddr);
-}
-
-
-/* Forks a process into the background, executing the supplied command, and
- * returns a socketpair made for bidirectional transfer with the children
- * process. Using this strategy the parent may have better control, like
- * shaping the network bandwidth of that process, and monitoring for network
- * inactivity. Returns TRUE on success, with the <pid> and <sock> pointers
- * initialized, or FALSE on failure.
- */
-static bool exec_popen(int *sock, pid_t *pid, const char *path,
-       char * const *argv, rlim_t *rl, struct iface *ifaces, int nifaces,
-       struct ipaddr_node *ipn, struct sockaddr *addr, const char *ipaddr)
-{
-    int sv[2];
-
-    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, &sv) == -1) {
-       syslog(LOG_NOTICE, "exec_popen() - socketpair() - (%s)",
-               strerror(errno));
-       return FALSE;
-    }
-    if ((*pid = fork()) == -1) {
-       syslog(LOG_NOTICE, "exec_popen() - fork() - (%s)",
-               strerror(errno));
-       (void) close(sv[0]);
-       (void) close(sv[1]);
-       return FALSE;
-    } else if (*pid > 0) {
-       /* Parent, close client side of socketpair, and return successfully. */
-       *sock = sv[0];
-       (void) close(sv[1]);
-       return TRUE;
-    } else {
-       struct sigaction act;
-       struct ifaces *tif;
-
-       /* Child successfully launched, we must cleanup before using
-        * exec_command()
-        */
-
-#ifndef __GLIBC__
-       setproctitle("Client server process");
-#endif /* __GLIBC */
-
-       /* We create our own process group so that the process after execve(2)
-        * could not kill(0) causing the listerner process to exit. It also
-        * allows us to optionally not interrupt currently served client when
-        * we restart.
-        */
-       (void) setsid();
-
-       /* Change signal handling policy. If we do not restore the signals we
-        * ignore to the default action, they will be ignored by the process
-        * after execve(2). Signals we are handling will automatically be
-        * restored to the default action.
-        */
-       act.sa_handler = SIG_DFL;
-       act.sa_flags = 0;
-       (void) sigemptyset(&act.sa_mask);
-
-       (void) sigaction(SIGTTOU, &act, NULL);
-       (void) sigaction(SIGTTIN, &act, NULL);
-       (void) sigaction(SIGTSTP, &act, NULL);
-       (void) sigaction(SIGPIPE, &act, NULL);
-
-       /* Let children know and remember these */
-       client.ipn = ipn;
-       client.saddr = *addr;
-       client.ipaddr = ipaddr;
-       /* Resolve if CONF.RESOLVE_ADDRESSES */
-       client_resolve();
-
-       /* Close all filedescriptors which this process should
-        * not have access it is also safe to drop the locks now.
-        */
-       for (tif = ifaces; *(tif->address) != '\0'; tif++) {
-           if (tif->sock != -1) {
-               (void) close(tif->sock);
-               tif->sock = -1;
-           }
-       }
-       shlocks_destroy(CONF.LOCK_PATH, locks, (enum shlocks)SHLOCK_MAX,
-               FALSE);
-       (void) close(server.runlock);
-       (void) close(server.alock);
-
-       /* stderr is already redirected to "/dev/null". Make sure that stdin
-        * and stdout are redirected to the client socket, and to close the
-        * extraneous filedescriptor.
-        */
-       (void) dup2(sv[1], 0);
-       (void) dup2(sv[1], 1);
-       (void) close(sv[1]);
-       (void) close(sv[0]);
-
-       /* We can finally attempt to launch our external executable after
-        * setting the rlimits, if any. If this fails, the process exists,
-        * and the parent socket end will be disconnected, a condition which
-        * it will need to detect.
-        */
-       exec_command(path, argv, rl);
-       /* NOTREACHED */
-    }
-}
-
-
-/* Safely executes the specified command, or exits.
- * This function never returns to the caller.
- * The command line can be parsed using mmstring(3)'s mm_cmdparse() first.
- * Perform sanity checking on the executable we will be launching.
- * We want to make sure that it is executable, but read-only, and that
- * it has no setuid/setgid bit set. We also ensure that it consists of
- * an executable rather than a script requireing an interpreter.
- * We also verify that the file is owned by the superuser.
- * We perform no globbing whatsoever and do not want to use a shell.
- */
-static void exec_command(const char *path, char * const *argv, rlim_t *rl)
-{
-    struct stat st;
-    mode_t mode;
-    int fd;
-    unsigned char buf[4];
-    char *const env[1] = {NULL};
-
-    /* If an array of 9 rlim_t was passed, attempt to set the ones which
-     * aren't supplied with -1.
-     */
-    if (rl != NULL) {
-       SETRLIMIT("RLIMIT_CORE", RLIMIT_CORE, rl[RL_CORE]);
-       SETRLIMIT("RLIMIT_CPU", RLIMIT_CPU, rl[RL_CPU]);
-       SETRLIMIT("RLIMIT_DATA", RLIMIT_DATA, rl[RL_DATA]);
-       SETRLIMIT("RLIMIT_FSIZE", RLIMIT_FSIZE, rl[RL_FSIZE]);
-       SETRLIMIT("RLIMIT_MEMLOCK", RLIMIT_MEMLOCK, rl[RL_MEMLOCK]);
-       SETRLIMIT("RLIMIT_NOFILE", RLIMIT_NOFILE, rl[RL_NOFILE]);
-       SETRLIMIT("RLIMIT_NPROC", RLIMIT_NPROC, rl[RL_NPROC]);
-       SETRLIMIT("RLIMIT_RSS", RLIMIT_RSS, rl[RL_RSS]);
-       SETRLIMIT("RLIMIT_STACK", RLIMIT_STACK, rl[RL_STACK]);
-    }
-
-    /* First make sure that command exists and is a regular file */
-    if (lstat(path, &st) != 0) {
-       syslog(LOG_NOTICE, "* exec_command() - lstat(%s) - (%s)", path,
-               strerror(errno));
-       exit(EXIT_FAILURE);
-    }
-    if (!S_ISREG(st.st_mode)) {
-       syslog(LOG_NOTICE, "* exec_command() - Not regular file (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    /* Reject it if it has any setuid/setgid bit set */
-    mode = st.st_mode & ~S_IFMT;
-    if (mode & S_ISUID) {
-       syslog(LOG_NOTICE, "* exec_command() - setuid file (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    if (mode & S_ISGID) {
-       syslog(LOG_NOTICE, "* exec_command() - setgid file (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    /* Has to be owned by root user for more safety */
-    if (st.st_uid != 0) {
-       syslog(LOG_NOTICE, "* exec_command() - Not owned by uid 0 (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    /* access(2) is safer than testing the mode bits. Make sure that we cannot
-     * write to the file, but that we can read and execute it.
-     */
-    if (access(path, W_OK) == 0) {
-       syslog(LOG_NOTICE, "* exec_command() - File writable (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    if (access(path, R_OK | X_OK) == -1) {
-       syslog(LOG_NOTICE, "* exec_command() - Not read/exec (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-    /* Now make sure that it does not consist of a script. We only support
-     * ELF executables for now for simplicity (static or dynamic ones).
-     */
-    if ((fd = open(path, O_RDONLY)) == -1) {
-       syslog(LOG_NOTICE, "* exec_command() - open(%s) - (%s)", path,
-               strerror(errno));
-       exit(EXIT_FAILURE);
-    }
-    if (read(fd, buf, 4) != 4) {
-       syslog(LOG_NOTICE, "* exec_command() - read(%s) - (%s)", path,
-               strerror(errno));
-       (void) close(fd);
-       exit(EXIT_FAILURE);
-    }
-    (void) close(fd);
-    if (buf[1] != 'E' || buf[2] != 'L' || buf[3] != 'F') {
-       syslog(LOG_NOTICE, "* exec_command() - Not ELF file (%s)", path);
-       exit(EXIT_FAILURE);
-    }
-
-    /* Finally attempt execution */
-    (void) execve(path, argv, env);
-
-    /* If we reach this point, execve(2) failed, and we must use _exit(2) for
-     * safety in this case.
-     */
-    _exit(EXIT_FAILURE);
-}
-
-
-/* If the maximum number of allowed connections has not been reached, increases
- * the counter and returns TRUE. Returns FALSE otherwise, in which case the
- * server should not allow more clients.
- */
-static bool connection_open(const char *ipaddr)
-{
-    if (server.current_connections == 0 && server.alock != -1) {
-       /* Attempt to lock alock */
-       if ((flock(server.alock, LOCK_EX | LOCK_NB)) == -1) {
-           syslog(LOG_NOTICE, "Refusing %s (ALOCK_PATH currently locked)",
-                   ipaddr);
-           return FALSE;
-       }
-    }
-    if (server.current_connections < CONF.MAX_CONNECTIONS) {
-       server.current_connections++;
-       return TRUE;
-    }
-    syslog(LOG_NOTICE, "Refusing %s (MAX_CONNECTIONS reached = %d)",
-           ipaddr, server.current_connections);
-
-    return FALSE;
-}
-
-
-/* Decreases the current number of total connections counter. */
-static void connection_close(void)
-{
-    if (server.current_connections > 0)
-       server.current_connections--;
-    else
-       DEBUG_PRINTF("connection_close", "server.current_connections < 1 !");
-    if (server.current_connections == 0 && server.alock != -1) {
-       /* Release alock */
-       (void) flock(server.alock, LOCK_UN);
-    }
-}
-
-
-/* These use shared memory and provide a nice API for use by the server. */
-
-/* If necessary, adds the address to the list of currently active connections.
- * If the address already was present, makes sure that it has not reached it's
- * maximum number of allowed connections and connection rate limits, and
- * increases it's counter. Returns a pointer to the ipaddr_node on success,
- * or NULL if the server should reject the connection, in which case the
- * reason and address are automatically logged via syslog(3) and mmstat(3).
- */
-static struct ipaddr_node *ipaddr_open(struct sockaddr *saddr,
-       const char *ipaddr)
-{
-    struct ipaddr_node *ipn = NULL;
-    bool ok = FALSE;
-    time_t now = time(NULL);
-
-    /* Make sure that we respect connection rates and limits for the addresses.
-     */
-    if ((flock(locks[SHLOCK_IPADDR], LOCK_EX)) == 0) {
-       struct sockaddr_in *sinaddr = (struct sockaddr_in *)saddr;
-
-       if ((ipn = (struct ipaddr_node *)hashtable_lookup(&shmem->ipaddr_table,
-                       &sinaddr->sin_addr.s_addr, sizeof(u_int32_t)))
-               == NULL) {
-           /* Create new entry */
-           if (HASHTABLE_NODES(&shmem->ipaddr_table) < CONF.MAX_ADDRESSES) {
-               if ((ipn = (struct ipaddr_node *)pool_alloc(
-                               &shmem->ipaddr_pool, FALSE)) != NULL) {
-                   /* Rate limiting and total connections initialization */
-                   LR_INIT(&ipn->lr, CONF.CONNECTION_RATE,
-                           CONF.CONNECTION_PERIOD, now);
-                   ipn->connections = 0;
-                   /* Cache nodes initialization */
-                   ipn->address = *saddr;
-                   *ipn->hostname = '\0';
-                   (void) hashtable_link(&shmem->ipaddr_table,
-                          (hashnode_t *)ipn,
-                           &((struct sockaddr_in *)&ipn->address)->
-                           sin_addr.s_addr, sizeof(u_int32_t));
-               } else
-                   DEBUG_PRINTF("ipaddr_open", "pool_alloc()");
-           } else {
-               syslog(LOG_NOTICE,
-                       "Refusing %s for exceeded number of addresses (%ld)",
-                       ipaddr, CONF.MAX_ADDRESSES);
-           }
-       }
-       if (ipn != NULL) {
-           /* Either the node was found or successfully created */
-           if (ipn->connections < CONF.MAX_PER_ADDRESS) {
-               if (CONF.CONNECTION_RATE > 0) {
-                   if (lr_allow(&ipn->lr, 1, now, FALSE))
-                       ok = TRUE;
-                   else {
-                       syslog(LOG_NOTICE,
-                               "Refusing %s for exceeded connection rate \
-(%ld connections in %ld seconds, %ld seconds left to clear)",
-                       ipaddr, LR_POSTS(&ipn->lr), CONF.CONNECTION_PERIOD,
-                       LR_REMAINS(&ipn->lr, now));
-                   }
-               } else
-                   ok = TRUE;
-           } else {
-               syslog(LOG_NOTICE, "Refusing %s for exceeded number of \
-connections per address (%ld)", ipaddr, CONF.MAX_PER_ADDRESS);
-           }
-       }
-
-       if (ok)
-           ipn->connections++;
-       else
-           ipn = NULL;
-
-       (void) flock(locks[SHLOCK_IPADDR], LOCK_UN);
-    }
-
-    return ipn;
-}
-
-
-/* Decreases the current number of connections for the specified address, and
- * if necessary, frees the entry from the table if no more connections exist
- * for this address. The node is expected to exist and to represent the right
- * one obtained from ipaddr_open().
- */
-static void ipaddr_close(struct ipaddr_node *ipn)
-{
-    if (ipn != NULL) {
-       if ((flock(locks[SHLOCK_IPADDR], LOCK_EX)) == 0) {
-           ipn->connections--;
-           /* Leave the cache service process delete the entries, which
-            * allows us to keep statistics for rate limiting, as well as
-            * cache hostnames on a per-address basis.
-            */
-           (void) flock(locks[SHLOCK_IPADDR], LOCK_UN);
-       }
-    }
-}
-
-
-/* Launches the ipaddress-hostname-rate cache entry expiration process,
- * a kind of asynchroneous garbage collector.
- */
-static pid_t launch_ipaddr_expire_process(uid_t uid, gid_t *gids, int ngids)
-{
-    pid_t pid = -1;
-
-    if ((pid = fork()) == 0) {
-       struct sigaction act;
-
-       /* Reset default signal action */
-       act.sa_handler = SIG_DFL;
-       act.sa_flags = SA_NOCLDSTOP;
-       (void) sigemptyset(&act.sa_mask);
-
-       (void) sigaction(SIGTERM, &act, NULL);
-       (void) sigaction(SIGINT, &act, NULL);
-       (void) sigaction(SIGCHLD, &act, NULL);
-       (void) sigaction(SIGSEGV, &act, NULL);
-
-       /* Release runlock which only our parent should hold */
-       (void) close(server.runlock);
-
-       /* Drop privileges */
-       if (!mmdropprivs(uid, gids, ngids)) {
-           syslog(LOG_NOTICE, "launch_ipaddr_expire_process() - Cannot \
-change uid and gids to safe privs");
-           (void) kill(0, SIGTERM);
-           (void) exit(EXIT_FAILURE);
-       }
-       ipaddr_expire_process();
-       /* NOTREACHED */
-    }
-
-    /* Parent */
-    return pid;
-}
-
-
-/* A quick hashtable_hash() and memcmp() replacements which already deal with
- * unique 32-bit values.
- */
-
-/* ARGSUSED */
-static u_int32_t key_hash32(const void *data, size_t len)
-{
-    return *((u_int32_t *)data);
-}
-
-/* ARGSUSED */
-static int key_cmp32(const void *src, const void *dst, size_t len)
-{
-    return *((u_int32_t *)src) - *((u_int32_t *)dst);
-}
-
-/* And to make things right, to not assume that pid_t is a u_int32_t, do
- * the same.
- */
-
-/* ARGSUSED */
-static u_int32_t key_pidhash(const void *data, size_t len)
-{
-    return (u_int32_t)*((pid_t *)data);
-}
-
-/* ARGSUSED */
-static int key_pidcmp(const void *src, const void *dst, size_t len)
-{
-    return *((pid_t *)src) - *((pid_t *)dst);
-}
-
-
-/* This process can run independantly and manage the ipaddr cache entry
- * expiration events.
- */
-static void ipaddr_expire_process(void)
-{
-    struct ipaddr_expire_process_iterator_udata data;
-
-#ifndef __GLIBC__
-    setproctitle("Cache service process");
-#endif /* __GLIBC__ */
-
-    /* Set initial timeout to maximum allowed */
-    data.soonest = CONF.CONNECTION_PERIOD;
-    for (;;) {
-       /* Sleep until it is known that at least one node expired */
-       (void) sleep(data.soonest);
-       /* Tell our iterator function the current time and the maximum
-        * allowed time to wait to
-        */
-       data.current = time(NULL);
-       data.soonest = CONF.CONNECTION_PERIOD;
-       /* Lock table, reset expired nodes, garbage collect, and set
-        * data.soonest to the delay of the soonest next expireing node.
-        */
-       if ((flock(locks[SHLOCK_IPADDR], LOCK_EX)) == 0) {
-           if (HASHTABLE_NODES(&shmem->ipaddr_table) > 0)
-               hashtable_iterate(&shmem->ipaddr_table,
-                       ipaddr_expire_process_iterator, &data);
-           (void) flock(locks[SHLOCK_IPADDR], LOCK_UN);
-       }
-    }
-    /* NOTREACHED */
-}
-
-
-/* Internally used by the cache events expiration process */
-static bool ipaddr_expire_process_iterator(hashnode_t *hnod, void *udata)
-{
-    struct ipaddr_node *node = (struct ipaddr_node *)hnod;
-    struct ipaddr_expire_process_iterator_udata *data = udata;
-    time_t rem;
-
-    /* If the node expired, reset it. For nodes which do not, record the
-     * soonest to expire node's delay. For those which expire and for which
-     * no connections exist anymore, expunge them.
-     */
-    if ((rem = LR_REMAINS(&node->lr, data->current)) == 0) {
-       /* This entry expired */
-       if (node->connections == 0) {
-           /* Safe to expunge this entry */
-           hashtable_unlink(&shmem->ipaddr_table, (hashnode_t *)node);
-           (void) pool_free((pnode_t *)node);
-       } else {
-           /* Reset it */
-           LR_EXPIRE(&node->lr, data->current);
-           rem = LR_REMAINS(&node->lr, data->current);
-       }
-    }
-    if (rem != 0 && data->soonest > rem)
-       data->soonest = rem;
-
-    return TRUE;
-}
diff --git a/mmsoftware/mmspawnd2/GNUmakefile b/mmsoftware/mmspawnd2/GNUmakefile
deleted file mode 100644 (file)
index c297288..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# $Id: GNUmakefile,v 1.2 2004/10/05 15:39:47 mmondor Exp $
-
-MMLIBS := $(addprefix ../mmlib/,mmpool.o mmlog.o mmreadcfg.o mmstring.o \
-mmhash.o mmalarm.o mmheap.o mmlimitrate.o mmserver2.o)
-OBJS := mmspawnd.o
-CFLAGS += -Wall
-
-all: mmspawnd
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I../mmlib -o $@ $<
-
-mmspawnd: $(MMLIBS) $(OBJS)
-       cc -o $@ $(OBJS) -lc $(MMLIBS)
-
-install: all
-       install -cs -o 0 -g 0 -m 500 mmspawnd /usr/local/sbin
-#      install -c -o 0 -g 0 -m 444 mmspawnd.conf.5 /usr/local/man/man5
-#      install -c -o 0 -g 0 -m 444 mmspawnd.8 /usr/local/man/man8
-
-clean:
-       rm -f mmspawnd $(OBJS) $(MMLIBS)
diff --git a/mmsoftware/mmspawnd2/mmspawnd.8 b/mmsoftware/mmspawnd2/mmspawnd.8
deleted file mode 100644 (file)
index 5c892e1..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-.\" $Id: mmspawnd.8,v 1.1 2005/11/17 13:32:24 mmondor Exp $
-.\"
-.\" Copyright (C) 2003, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\" 5. Redistribution of source code may not be released under the terms of
-.\"    any GNU Public License derivate.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd October 28, 2003
-.Dt MMSPAWND 8
-.Os mmsoftware
-.Sh NAME
-.Nm mmspawnd
-.Nd
-.Xr inetd 8
-alternative for better security
-.Sh SYNOPSIS
-.Nm mmspawnd Op Ar config_file
-.Sh DESCRIPTION
-.Nm
-is a useful replacement for
-.Xr inetd 8
-when security is a concern. It only allows to serve one service per running
-instance, but a different configuration file can be provided for each service
-to run several ones as required. It supports connection number and rate limits
-on a global and per-address basis,
-.Xr chroot 2
-and
-.Xr setrlimit 2 . It will only
-.Xr bind 2
-to specified addresses/interfaces to listen for connections.
-It also ensures to drop privileges definitely before starting operation, using
-.Xr setgid 2 ,
-.Xr setuid 2
-and
-.Xr setgroups 2 .
-.Pp
-Further, it comports a safe
-.Xr execve 2
-wrapper which ensures to not pass unexpected arguments or environmental
-variables, as well as to only execute ELF binaries which are owned by the
-superuser and non-writable. No globbing whatsoever is performed by it,
-and it only allows an absolute path to be provided to the application to
-launch. It will not allow execution of files with the setuid or setgid
-bits set.
-.Pp
-All connections are logged via the specified facility using
-.Xr syslog 3 ,
-as well as the exit code of the application when closing the connection with
-the client. Any security issue encoutered by the
-.Xr execve 2
-wrapper is also logged.
-.Pp
-It's default configuration makes it harmless but useless. See the
-.Xr mmspawnd.conf 5
-manual page for configuration file description.
-.Pp
-A good usage for
-.Xr mmspawnd 8
-is for instance to run a CVS pserver in safe conditions. It then can be
-restrited to the specified root directory, and access the files with read-only
-access under an unprivileged user. If used for this purpose, also look at
-the
-.Xr mmanoncvs 8
-manual page.
-.Pp
-Another interesting feature is being able to specify if the currently running
-clients should be interrupted or not if the
-.Nm
-server is to be stopped or restarted. In the case of a CVS checkout for
-instance, if
-.Nm KILL_CHILDREN
-configuration option is FALSE, the operation will continue until it finishes
-normally, even in the event of a server configuration change or restart.
-.Pp
-For additional security, only the superuser is allowed to launch
-.Nm ,
-unless compiled with the
-.Nm -DNODROPPRIVS
-option, in which case it could be used by a nonprivileged user to bind
-a service to a high port, and server refuse to be launched by root.
-Other users attempting to launch the service will cause a line to be logged,
-telling which user ID attempted the launch.
-.Pp
-When launched successfully, a status line is logged telling under which 
-user ID it runs, which port it listens to and on which addresses/interfaces,
-as well as the configuration file location and service command.
-.Pp
-Note that this system redirects the stderr stream (filedescriptor 2) of
-the command launched to serve the clients to the "/dev/null" device, so that
-errors output from it be not disclosed to the remote user.
-.Pp
-Another optional interesting feature which it offers is the possibility
-to use advisory locking on a special control file to synchronize the service
-with another program. The lock is acquired in exclusive mode by
-.Nm
-when at least one connection exists being served. It is released when no
-more connections remain. This way, another program can rely on the fact that
-noone is using the service if it can obtain the lock. As long as the other
-application holds the lock, the service will refuse new connections. Normal
-service resumes immediately as the lock is released by the third party
-application. Of course, it is important to properly configure the permissions
-on that lock file, if the feature is enabled.
-.Pp
-Eventual support for bandwidth shaping/throttling and network inactivity
-timeout limits are planned. However, as those will require a redesign and
-rewrite of
-.Nm ,
-all we support for now is total maximum timeout for execution of the supplied
-service command. This is still better than
-.Xr inetd 8
-behavior, however.
-.Sh FILES
-.Bl -tag -width indent -offset indent
-.It Pa /usr/local/sbin/mmspawnd
-The actual server binary
-.It Pa /usr/local/etc/mmspawnd.conf
-The default configuration file to read
-.El
-.Sh AUTHOR
-.Nm
-was written by Matthew Mondor, and is
-Copyright (c) 2003, Matthew Mondor, All Rights Reserved.
-.Sh SEE ALSO
-.Xr mmspawnd.conf 5 ,
-.Xr bind 2 ,
-.Xr chroot 2 ,
-.Xr setrlimit 2 ,
-.Xr setuid 2 ,
-.Xr setgid 2 ,
-.Xr setgroups 2 ,
-.Xr mmanoncvs 8 ,
-.Xr inetd 8 .
-.Sh BUGS
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/mmspawnd2/mmspawnd.c b/mmsoftware/mmspawnd2/mmspawnd.c
deleted file mode 100644 (file)
index 7e74fdf..0000000
+++ /dev/null
@@ -1,794 +0,0 @@
-/* $Id: mmspawnd.c,v 1.9 2005/03/01 15:18:21 mmondor Exp $ */
-
-/*
- * Copyright (C) 2004, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * TODO:
- * - Test setrlimit(2) support
- * - Support option to allow to send the stderr output of launched processes
- *   to a file for debugging. This however requires support in mmserver2(3)
- *   for this. This would only be for debugging, especially because of the
- *   fact that multiple processes could attempt to append at the end of the
- *   same file at once, concurrently. We can't really use a lock either, since
- *   we won't be controlling the output, unless we used a popen(3)-like
- *   system.
- */
-
-
-#include <sys/types.h>
-#include <sys/resource.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>            /* strerror(3) */
-#include <syslog.h>
-#include <unistd.h>
-
-#include <mmtypes.h>
-#include <mmreadcfg.h>
-#include <mmstring.h>
-#include <mmserver2.h>
-
-
-
-/* DEFINITIONS */
-
-struct config {
-       char PROCTITLE[256], SYSLOG_FACILITY[32], PID_PATH[256],
-           LOCK_PATH[256], SHLOCKS_PATH[256], ALOCK_PATH[256],
-           ALOCK_USER[32], ALOCK_GROUP[32], ALOCK_MODE[4], ALOCK_ERRMSG[256],
-           CHROOT_DIR[256], COMMAND[256], USER[32], GROUPS[64],
-           LISTEN_TO[256];
-       long COMMAND_MAX_ARGS, CHILDREN_INITIAL, CHILDREN_MINSPARE,
-           CHILDREN_MAXSPARE, CHILDREN_MAXIMUM, ADDRESS_CACHE_SIZE,
-           ADDRESS_CACHE_RATE_LIMIT, ADDRESS_CACHE_RATE_PERIOD,
-           ADDRESS_CACHE_CONCURRENCY_LIMIT, LIMIT_CORE, LIMIT_CPU,
-           LIMIT_DATA, LIMIT_FSIZE, LIMIT_MEMLOCK, LIMIT_NOFILE,
-           LIMIT_NPROC, LIMIT_RSS, LIMIT_STACK;
-       bool EXIT_KILL_CHILDREN, CHILDREN_SETSID, ADDRESS_RESOLVE,
-           ADDRESS_RATE_LIMITS, ADDRESS_CONCURRENCY_LIMITS,
-           EXECUTABLE_SECURITY, RLIMITS;
-};
-
-
-
-/* PROTOTYPES */
-
-int            main(int, char **);
-
-static int     setsockopts(int);
-static int     config_read(const char *, uid_t *, gid_t **, int *);
-static int     lock_check(const char *);
-static int     alock_init(const char *, uid_t, gid_t, mode_t);
-static int     listen_to(const char *);
-static int     rlimit_security(void);
-static int     executable_security(const char *);
-static int     child_init_hook(void);
-static void    request_handler(struct server_request *);
-
-
-
-/* GLOBALS */
-
-static struct config   CONF;
-static char            daemon_title[64];
-
-static int             parent_alock;
-static int             child_alock_fd;
-static size_t          alock_errmsg_len;
-
-static char            *command_line;
-static char            *command;
-static int             command_argc;
-static char            **command_argv;
-
-/* For mmreadcfg() */
-static carg_t  cargs[] = {
-       {CAT_STR, CAF_NONE, 1, 63, "PROCTITLE", CONF.PROCTITLE},
-       {CAT_STR, CAF_NONE, 1, 31, "SYSLOG_FACILITY", CONF.SYSLOG_FACILITY},
-       {CAT_STR, CAF_NONE, 1, 255, "PID_PATH", CONF.PID_PATH},
-       {CAT_STR, CAF_NONE, 1, 255, "LOCK_PATH", CONF.LOCK_PATH},
-       {CAT_STR, CAF_NONE, 1, 255, "SHLOCKS_PATH", CONF.SHLOCKS_PATH},
-       {CAT_STR, CAF_NONE, 1, 255, "ALOCK_PATH", CONF.ALOCK_PATH},
-       {CAT_STR, CAF_NONE, 1, 31, "ALOCK_USER", CONF.ALOCK_USER},
-       {CAT_STR, CAF_NONE, 1, 31, "ALOCK_GROUP", CONF.ALOCK_GROUP},
-       {CAT_STR, CAF_NONE, 1, 3, "ALOCK_MODE", CONF.ALOCK_MODE},
-       {CAT_STR, CAF_NONE, 1, 255, "ALOCK_ERRMSG", CONF.ALOCK_ERRMSG},
-       {CAT_STR, CAF_NONE, 1, 255, "CHROOT_DIR", CONF.CHROOT_DIR},
-       {CAT_STR, CAF_NONE, 1, 255, "COMMAND", CONF.COMMAND},
-       {CAT_STR, CAF_NONE, 1, 31, "USER", CONF.USER},
-       {CAT_STR, CAF_NONE, 1, 63, "GROUPS", CONF.GROUPS},
-       {CAT_STR, CAF_NONE, 1, 255, "LISTEN_TO", CONF.LISTEN_TO},
-       {CAT_VAL, CAF_NONE, 1, 63, "COMMAND_MAX_ARGS",
-               &CONF.COMMAND_MAX_ARGS},
-       {CAT_VAL, CAF_NONE, 1, 1024, "CHILDREN_INITIAL",
-               &CONF.CHILDREN_INITIAL},
-       {CAT_VAL, CAF_NONE, 1, 1024, "CHILDREN_MINSPARE",
-               &CONF.CHILDREN_MINSPARE},
-       {CAT_VAL, CAF_NONE, 1, 1024, "CHILDREN_MAXSPARE",
-               &CONF.CHILDREN_MAXSPARE},
-       {CAT_VAL, CAF_NONE, 1, 1024, "CHILDREN_MAXIMUM",
-               &CONF.CHILDREN_MAXIMUM},
-       {CAT_VAL, CAF_NONE, 0, 4096, "ADDRESS_CACHE_SIZE",
-               &CONF.ADDRESS_CACHE_SIZE},
-       {CAT_VAL, CAF_NONE, 0, 4096, "ADDRESS_CACHE_RATE_LIMIT",
-               &CONF.ADDRESS_CACHE_RATE_LIMIT},
-       {CAT_VAL, CAF_NONE, 0, 1800, "ADDRESS_CACHE_RATE_PERIOD",
-               &CONF.ADDRESS_CACHE_RATE_PERIOD},
-       {CAT_VAL, CAF_NONE, 0, 1024, "ADDRESS_CACHE_CONCURRENCY_LIMIT",
-               &CONF.ADDRESS_CACHE_CONCURRENCY_LIMIT},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_CORE", &CONF.LIMIT_CORE},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_CPU", &CONF.LIMIT_CPU},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_DATA", &CONF.LIMIT_DATA},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_FSIZE", &CONF.LIMIT_FSIZE},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_MEMLOCK", &CONF.LIMIT_MEMLOCK},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_NOFILE", &CONF.LIMIT_NOFILE},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_NPROC", &CONF.LIMIT_NPROC},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_RSS", &CONF.LIMIT_RSS},
-        {CAT_VAL, CAF_NONE, 0, 0, "RLIMIT_STACK", &CONF.LIMIT_STACK},
-       {CAT_BOOL, CAF_NONE, 0, 0, "EXIT_KILL_CHILDREN",
-               &CONF.EXIT_KILL_CHILDREN},
-       {CAT_BOOL, CAF_NONE, 0, 0, "CHILDREN_SETSID", &CONF.CHILDREN_SETSID},
-       {CAT_BOOL, CAF_NONE, 0, 0, "ADDRESS_RESOLVE", &CONF.ADDRESS_RESOLVE},
-       {CAT_BOOL, CAF_NONE, 0, 0, "ADDRESS_RATE_LIMITS",
-               &CONF.ADDRESS_RATE_LIMITS},
-       {CAT_BOOL, CAF_NONE, 0, 0, "ADDRESS_CONCURRENCY_LIMITS",
-               &CONF.ADDRESS_CONCURRENCY_LIMITS},
-       {CAT_BOOL, CAF_NONE, 0, 0, "EXECUTABLE_SECURITY",
-               &CONF.EXECUTABLE_SECURITY},
-       {CAT_BOOL, CAF_NONE, 0, 0, "RLIMITS", &CONF.RLIMITS},
-       {CAT_END, CAF_NONE, 0, 0, NULL, NULL}
-};
-static cmap_t  cmap[] = {
-       {"LOG_AUTH", LOG_AUTH},
-       {"LOG_AUTHPRIV", LOG_AUTHPRIV},
-       {"LOG_CRON", LOG_CRON},
-       {"LOG_DAEMON", LOG_DAEMON},
-       {"LOG_FTP", LOG_FTP},
-       {"LOG_LPR", LOG_LPR},
-       {"LOG_MAIL", LOG_MAIL},
-       {"LOG_NEWS", LOG_NEWS},
-       {"LOG_SYSLOG", LOG_SYSLOG},
-       {"LOG_USER", LOG_USER},
-       {"LOG_UUCP", LOG_UUCP},
-       {NULL, 0}
-};
-
-
-
-/* TEXT */
-
-int
-main(int argc, char **argv)
-{
-       struct server_config            c;
-       uid_t                           uid, alock_uid;
-       gid_t                           *gids, alock_gid;
-       mode_t                          alock_mode;
-       int                             ngids, ch;
-       char                    *conf_file = "/usr/local/etc/mmspawnd.conf";
-
-       /*
-        * Make sure that only the superuser may launch this daemon
-        */
-       if (getuid() != 0) {
-               (void) fprintf(stderr,
-                   "Only can be started by the superuser\n");
-               syslog(LOG_NOTICE,
-                   "User %d attempted to launch mmspawnd with '%s'",
-                   getuid(), conf_file);
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * Parse command line arguments
-        */
-       while ((ch = getopt(argc, argv, "f:")) != -1) {
-               switch (ch) {
-               case 'f':
-                       conf_file = optarg;
-                       break;
-               case '?':
-                       /* FALLTHROUGH */
-               default:
-                       (void) fprintf(stderr,
-                           "usage: mmspawnd [-f <configfile>]\n");
-                       exit(EXIT_FAILURE);
-               }
-       }
-       argc -= optind;
-       argv += optind;
-
-       /*
-        * Things we must do before calling chroot(2)
-        */
-
-       /* Read config file. This also calls openlog(3) for us */
-       if (config_read(conf_file, &uid, &gids, &ngids) == -1) {
-               (void) fprintf(stderr, "Error reading configuration file."
-                   " Verify syslog for more details.\n");
-               exit(EXIT_FAILURE);
-       }
-
-       /* Make sure that we're not already running */
-       if (lock_check(CONF.LOCK_PATH) == -1) {
-               (void) fprintf(stderr, "Already running!? - %s\n",
-                   strerror(errno));
-               syslog(LOG_NOTICE, "Already running!? - %s", strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * Verify if ALOCK is enabled, and if so, make sure to get proper
-        * permissions settings to create it.
-        */
-       if ((alock_uid = mmgetuid(CONF.ALOCK_USER)) == -1) {
-               syslog(LOG_NOTICE, "Unknown user '%s'", CONF.ALOCK_USER);
-               exit(EXIT_FAILURE);
-       }
-       if ((alock_gid = mmgetgid(CONF.ALOCK_GROUP)) == -1) {
-               syslog(LOG_NOTICE, "Unknown group '%s'", CONF.ALOCK_GROUP);
-               exit(EXIT_FAILURE);
-       }
-       alock_mode = (mode_t)strtol(CONF.ALOCK_MODE, NULL, 8);
-       if (alock_mode == 0 || alock_mode > 0770) {
-               syslog(LOG_NOTICE, "\nIllegal ALOCK_MODE '%03o'", alock_mode);
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * Chroot if wanted. Note that server_start() will chdir(2), but since
-        * we can setup the ALOCK, we chdir(2) here as well.
-        */
-       if (*CONF.CHROOT_DIR != '\0') {
-               if (chroot(CONF.CHROOT_DIR) == -1) {
-                       syslog(LOG_NOTICE, "chroot(%s) - %s", CONF.CHROOT_DIR,
-                           strerror(errno));
-                       exit(EXIT_FAILURE);
-               }
-               (void) chdir("/");
-       }
-
-       /*
-        * Create ALOCK file with specified permissions, so that third party
-        * applications, such as mmanoncvs(8) be able to update the CVS
-        * repository without allowing corrupted CVS checkout/update results.
-        */
-       if (alock_init(CONF.ALOCK_PATH, alock_uid, alock_gid, alock_mode)
-           == -1)
-               exit(EXIT_FAILURE);
-
-       /*
-        * Bind network server ports.
-        */
-       server_init();
-       if (listen_to(CONF.LISTEN_TO) == -1)
-               exit(EXIT_FAILURE);
-
-       /*
-        * Finally drop privileges.
-        */
-       if (!mmdropprivs(uid, gids, ngids)) {
-               syslog(LOG_NOTICE, "Error dropping privileges - %s",
-                   strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * Initialize and start server. New user must be able to create lock
-        * files as necessary where specified in SHLOCKS_PATH configuration
-        * directive.
-        */
-       (void) mm_memclr(&c, sizeof(struct server_config));
-       (void) mm_strcpy(c.locks_path, CONF.SHLOCKS_PATH);
-       *c.locks_user = '\0';
-       *c.locks_group = '\0';
-       c.locks_mode = 0600;
-       (void) mm_strcpy(c.null_path, "/dev/null");
-       (void) mm_strcpy(c.pid_path, CONF.PID_PATH);
-       (void) mm_strncpy(c.proc_title, CONF.PROCTITLE, 31);
-       c.children_initial = CONF.CHILDREN_INITIAL;
-       c.children_minspare = CONF.CHILDREN_MINSPARE;
-       c.children_maxspare = CONF.CHILDREN_MAXSPARE;
-       c.children_maximum = CONF.CHILDREN_MAXIMUM;
-       c.children_average_seconds = 300;
-       c.children_maxrequests = 1000;
-       c.serialization_lock = TRUE;
-       c.exit_interrupt_requests = CONF.EXIT_KILL_CHILDREN;
-       c.children_setsid = CONF.CHILDREN_SETSID;
-       c.using_execve = TRUE;
-       c.parent_init_hook = NULL;
-       c.parent_exit_hook = NULL;
-       c.parent_sighup_hook = NULL;
-       c.parent_timer_hook = NULL;
-       c.parent_timer_seconds = 0;
-       c.child_init_hook = child_init_hook;
-       c.child_exit_hook = NULL;
-       c.child_sigalrm_hook = NULL;
-       if (server_start(&c) == -1)
-               exit(EXIT_FAILURE);
-
-       /* NOTREACHED */
-       exit(EXIT_SUCCESS);
-}
-
-static int
-config_read(const char *file, uid_t *uid, gid_t **gids, int *ngids)
-{
-       cres_t  cres;
-       long    facility;
-
-       /*
-        * Set configuration defaults
-        */
-       *CONF.PROCTITLE = '\0';
-       (void) mm_strcpy(CONF.SYSLOG_FACILITY, "LOG_DAEMON");
-       (void) mm_strcpy(CONF.PID_PATH, "/var/run/mmspawnd.pid");
-       (void) mm_strcpy(CONF.LOCK_PATH, "/var/run/mmspawnd-lock");
-       (void) mm_strcpy(CONF.SHLOCKS_PATH, "/var/run/mmspawnd-lock");
-       *CONF.ALOCK_PATH = '\0';
-       (void) mm_strcpy(CONF.ALOCK_USER, "mmspawnd");
-       (void) mm_strcpy(CONF.ALOCK_GROUP, "mmspawnd");
-       (void) mm_strcpy(CONF.ALOCK_MODE, "660");
-       *CONF.ALOCK_ERRMSG = '\0';
-       *CONF.CHROOT_DIR = '\0';
-       (void) mm_strcpy(CONF.COMMAND, "/sbin/nologin");
-       (void) mm_strcpy(CONF.USER, "mmspawnd");
-       (void) mm_strcpy(CONF.GROUPS, "mmspawnd");
-       (void) mm_strcpy(CONF.LISTEN_TO, "127.0.0.1:2323");
-       CONF.CHILDREN_INITIAL = 5;
-       CONF.CHILDREN_MINSPARE = 5;
-       CONF.CHILDREN_MAXSPARE = 10;
-       CONF.CHILDREN_MAXIMUM = 32;
-       CONF.EXIT_KILL_CHILDREN = TRUE;
-       CONF.CHILDREN_SETSID = FALSE;
-       CONF.ADDRESS_RESOLVE = FALSE;
-       CONF.ADDRESS_RATE_LIMITS = FALSE;
-       CONF.ADDRESS_CONCURRENCY_LIMITS = FALSE;
-       CONF.ADDRESS_CACHE_SIZE = 0;
-       CONF.ADDRESS_CACHE_RATE_LIMIT = 0;
-       CONF.ADDRESS_CACHE_RATE_PERIOD = 0;
-       CONF.ADDRESS_CACHE_CONCURRENCY_LIMIT = 0;
-       CONF.EXECUTABLE_SECURITY = FALSE;
-       CONF.RLIMITS = FALSE;
-       CONF.LIMIT_CORE = -1;
-       CONF.LIMIT_CPU = -1;
-       CONF.LIMIT_DATA = -1;
-       CONF.LIMIT_FSIZE = -1;
-       CONF.LIMIT_MEMLOCK = -1;
-       CONF.LIMIT_NOFILE = -1;
-       CONF.LIMIT_NPROC = -1;
-       CONF.LIMIT_RSS = -1;
-       CONF.LIMIT_STACK = -1;
-
-       /*
-        * Read and parse configuration file
-        */
-       if (!mmreadcfg(&cres, cargs, file)) {
-               syslog(LOG_NOTICE, "Cannot read configuration file '%s'",
-                      file);
-               return -1;
-       }
-
-       /*
-        * Setup syslog. First perform sanity checking on supplied syslog
-        * facility string.
-        */
-       if (!mmmapstring(cmap, CONF.SYSLOG_FACILITY, &facility)) {
-               syslog(LOG_NOTICE, "Invalid syslog facility '%s'",
-                   CONF.SYSLOG_FACILITY);
-               return -1;
-       }
-       if (*CONF.PROCTITLE != '\0')
-               (void) snprintf(daemon_title, 63, "mmspawnd:%s",
-                   CONF.PROCTITLE);
-       else
-               (void) mm_strcpy(daemon_title, "mmspawnd");
-       openlog(daemon_title, LOG_PID | LOG_NDELAY, facility);
-
-       /*
-        * Now do some sanity checking on supplied users and groups, we'll
-        * return those properly if they are valid.
-        */
-       if ((*uid = mmgetuid(CONF.USER)) == -1) {
-               syslog(LOG_NOTICE, "Unknown user '%s'", CONF.USER);
-               return -1;
-       }
-       if (!(*gids = mmgetgidarray(ngids, CONF.GROUPS))) {
-               syslog(LOG_NOTICE, "At least one unknown group in '%s'",
-                   CONF.GROUPS);
-               return -1;
-       }
-
-       /* Prepare command line for execve(2) */
-       if ((command_line = _mm_strdup(CONF.COMMAND)) == NULL) {
-               syslog(LOG_NOTICE, "Out of memory copying '%s'",
-                   CONF.COMMAND);
-               return -1;
-       }
-       if ((command_argv = malloc(
-           sizeof(char *) * (CONF.COMMAND_MAX_ARGS + 2))) == NULL) {
-               syslog(LOG_NOTICE, "Out of memory allocating argv");
-               return -1;
-       }
-       if (!mm_cmdparse(&command, &command_argc, command_argv, command_line,
-           CONF.COMMAND_MAX_ARGS + 2)) {
-               syslog(LOG_NOTICE,
-                   "Error parsing COMMAND '%s', also check COMMAND_MAX_ARGS",
-                   CONF.COMMAND);
-               return -1;
-       }
-
-       /* Everything successful */
-       return 0;
-}
-
-/*
- * Function to verify if we are already running. Every configuration should
- * provide a lock file path to do this check.
- */
-static int
-lock_check(const char *file)
-{
-       int fd;
-
-       if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600)) != -1) {
-               if (flock(fd, LOCK_EX | LOCK_NB) == 0)
-                       return 0;
-               close(fd);
-       }
-
-       return -1;
-}
-
-/*
- * Set wanted setsockopt(2) on sockets. This function is called internally for
- * each socket we create using server_socket_bind().
- */
-static int
-setsockopts(int fd)
-{
-       struct linger   l;
-
-#define SETSOCKOPT(l, o)       do {                                    \
-       int     _o = 1;                                                 \
-       if ((setsockopt(fd, (l), (o), &_o, sizeof(int))) == -1)         \
-               return -1;                                              \
-} while (/* CONSTCOND */0)
-
-       SETSOCKOPT(SOL_SOCKET, SO_REUSEADDR);
-       SETSOCKOPT(SOL_SOCKET, SO_REUSEPORT);
-       SETSOCKOPT(SOL_SOCKET, SO_KEEPALIVE);
-
-#undef SETSOCKOPT
-
-       l.l_onoff = 0;
-       l.l_linger = 0;
-       if ((setsockopt(fd, SOL_SOCKET, SO_LINGER, &l,
-                       sizeof(struct linger))) == -1)
-               return -1;
-
-       return 0;
-}
-
-static int
-alock_init(const char *file, uid_t uid, gid_t gid, mode_t mode)
-{
-       int     fd;
-
-       parent_alock = 0;
-
-       if (*CONF.ALOCK_PATH == '\0')
-               return 0;
-
-       if ((fd = open(CONF.ALOCK_PATH, O_WRONLY | O_CREAT, mode)) == -1) {
-               syslog(LOG_NOTICE, "create/open('%s') - %s",
-                   CONF.ALOCK_PATH, strerror(errno));
-               goto err;
-       }
-       if (fchmod(fd, mode) == -1) {
-               syslog(LOG_NOTICE, "chmod('%s',%03o) - %s",
-                   CONF.ALOCK_PATH, mode, strerror(errno));
-               goto err;
-       }
-       if (fchown(fd, uid, gid) == -1) {
-               syslog(LOG_NOTICE, "chown('%s',%d,%d) - %s'",
-                   CONF.ALOCK_PATH, uid, gid, strerror(errno));
-               goto err;
-       }
-
-       (void) close(fd);
-
-       if (*CONF.ALOCK_ERRMSG != '\0')
-               alock_errmsg_len = mm_strlen(CONF.ALOCK_ERRMSG);
-       else
-               alock_errmsg_len = 0;
-
-       parent_alock = 1;
-
-       return 0;
-
-err:
-       if (fd != -1)
-               (void) close(fd);
-
-       return -1;
-}
-
-/*
- * Starts listening to all specified address:port pairs. Returns 0 on
- * success, or -1 on error, logging the error via syslog(3).
- */
-static int
-listen_to(const char *addresses)
-{
-       char    *string, *tstring;
-       char    *entries[32], *cols[3];
-       int     i, nentries, err;
-
-       string = tstring = NULL;
-       err = 0;
-
-       if ((string = _mm_strdup(addresses)) == NULL) {
-               syslog(LOG_NOTICE, "listen_to() - Out of memory error");
-               return -1;
-       }
-
-       if ((nentries = mm_straspl(entries, string, 31)) < 1) {
-               syslog(LOG_NOTICE, "No <address>:<port> specified in "
-                   "LISTEN_TO configuration directive");
-               err = -1;
-               goto end;
-       }
-
-       for (i = 0; i < nentries; i++) {
-               struct server_socket_config     sc;
-
-               tstring = _mm_strdup(entries[i]);
-               if (mm_strspl(cols, entries[i], 2, ':') != 2) {
-                       syslog(LOG_NOTICE,
-                           "[%s] not a valid <address>:<port> entry in "
-                           "LISTEN_TO configuration directive", tstring);
-                       err = -1;
-                       goto end;
-               }
-
-               (void) mm_memclr(&sc, sizeof(struct server_socket_config));
-               sc.family = (mm_strchr(cols[0], ':') != NULL ?
-                   AF_INET6 : AF_INET);
-               sc.type = SOCK_STREAM;
-               sc.port = (int)strtol(cols[1], NULL, 10);
-               sc.backlog = CONF.CHILDREN_MAXIMUM;
-               sc.create_stream = FALSE;
-               sc.address_resolve = CONF.ADDRESS_RESOLVE;
-               sc.address_rate_limits = CONF.ADDRESS_RATE_LIMITS;
-               sc.address_concurrency_limits =
-                   CONF.ADDRESS_CONCURRENCY_LIMITS;
-               sc.address_cache_size = CONF.ADDRESS_CACHE_SIZE;
-               sc.address_cache_rate_limit = CONF.ADDRESS_CACHE_RATE_LIMIT;
-               sc.address_cache_rate_period = CONF.ADDRESS_CACHE_RATE_PERIOD;
-               sc.address_cache_concurrency_limit =
-                   CONF.ADDRESS_CACHE_CONCURRENCY_LIMIT;
-               sc.packet_size = 0;
-               (void) mm_strcpy(sc.bind_address, cols[0]);
-               *sc.socket_user = '\0';
-               *sc.socket_group = '\0';
-               sc.socket_mode = 0;
-               sc.setsockopts = setsockopts;
-               sc.request_handler = request_handler;
-               sc.reject_handler = NULL;
-               sc.request_interrupt_hook = NULL;
-               sc.request_close_hook = NULL;
-               sc.user_data = NULL;
-               if (server_socket_bind(&sc) == -1)
-                       syslog(LOG_NOTICE, "Error binding socket for [%s]",
-                           tstring);
-
-               free(tstring);
-               tstring = NULL;
-       }
-
-end:
-       if (string != NULL)
-               free(string);
-       if (tstring != NULL)
-               free(tstring);
-
-       return err;
-}
-
-static int
-rlimit_security(void)
-{
-       struct rlimit   rl;
-
-/*
- * Use some preprocessor magic to shorten and clean up repetitive code:
- */
-
-#define SETRLIMIT(restxt, resource, limit) do {                                \
-       if ((limit) != -1) {                                            \
-               rl.rlim_cur = rl.rlim_max = (rlim_t)(limit);            \
-               if (setrlimit((resource), &rl) == -1) {                 \
-                       syslog(LOG_NOTICE,                              \
-                           "* setrlimit(R%s, %ld) - (%s)",             \
-                           (restxt), (limit), strerror(errno));        \
-                       return -1;                                      \
-               }                                                       \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-#define SETRLIMIT2(n)  SETRLIMIT(#n, R##n, CONF.n)
-
-       SETRLIMIT2(LIMIT_CORE);
-       SETRLIMIT2(LIMIT_CPU);
-       SETRLIMIT2(LIMIT_DATA);
-       SETRLIMIT2(LIMIT_FSIZE);
-       SETRLIMIT2(LIMIT_MEMLOCK);
-       SETRLIMIT2(LIMIT_NOFILE);
-       SETRLIMIT2(LIMIT_NPROC);
-       SETRLIMIT2(LIMIT_RSS);
-       SETRLIMIT2(LIMIT_STACK);
-
-#undef SETRLIMIT2
-#undef SETRLIMIT
-
-       return 0;
-}
-
-static int
-executable_security(const char *file)
-{
-       struct stat     st;
-       mode_t          mode;
-
-       /*
-        * First make sure that command exists and consists of a regular file
-        */
-       if (lstat(file, &st) != 0) {
-               syslog(LOG_NOTICE, "executable_security() - lstat('%s')",
-                   file);
-               return -1;
-       }
-       if (!S_ISREG(st.st_mode)) {
-               syslog(LOG_NOTICE,
-                   "executable_security() - '%s' not a regular file",
-                   file);
-               return -1;
-       }
-       /*
-        * Now make sure that it has no setuid/setgid bits set
-        */
-       mode = st.st_mode & ~S_IFMT;
-       if ((mode & S_ISUID) != 0) {
-               syslog(LOG_NOTICE, "executable_security() - '%s' is setuid",
-                   file);
-               return -1;
-       }
-       if ((mode & S_ISGID) != 0) {
-               syslog(LOG_NOTICE, "executable_security() - '%s' is setgid",
-                   file);
-               return -1;
-       }
-       /*
-        * Make sure it's owned by the superuser for more safety
-        */
-       if (st.st_uid != 0) {
-               syslog(LOG_NOTICE,
-                   "executable_security() - '%s' not owned by superuser",
-                   file);
-               return -1;
-       }
-       /*
-        * access(2) is safer than testing mode bits in this case, make sure
-        * that file is not writable.
-        */
-       if (access(file, W_OK) == 0) {
-               syslog(LOG_NOTICE,
-                   "executable_security() - '%s' not readonly", file);
-               return -1;
-       }
-
-       return 0;
-}
-
-static int
-child_init_hook(void)
-{
-
-       /*
-        * If the ALOCK feature is enabled, attempt to open the lock file and
-        * store the file descriptor for request_handler() to be able to use
-        * it.
-        */
-       if (parent_alock) {
-               if ((child_alock_fd = open(CONF.ALOCK_PATH, O_RDONLY))
-                   == -1) {
-                       syslog(LOG_NOTICE, "Could not open ALOCK '%s' - %s",
-                           CONF.ALOCK_PATH, strerror(errno));
-                       return -1;
-               }
-       } else
-               child_alock_fd = -1;
-
-       return 0;
-}
-
-/*
- * Actual server request handler function, internally called by the
- * mmserver2(3) system. We are allowed to use execve(2) here, since
- * we specified so in the initial server configuration. If we do not
- * do it for whatever reason, the process can be reused to serve other
- * requests for better performance. If we do call execve(2), the process
- * will die and be recycled. server_execve(), unlike execve(2), never returns,
- * since it will internally call _exit(2) as necessary if execve(2) fails.
- */
-static void
-request_handler(struct server_request *r)
-{
-
-       syslog(LOG_NOTICE, "Request from [%s]", r->client_address_name);
-
-       /*
-        * Verify if we have a filedescriptor to the ALOCK file (if any).
-        * If so, attempt non-blocking read/shared advisory lock in it.
-        * If we can't obtain the lock, abort request, optionally sending a
-        * message over the socket before closing the client connection.
-        * If we successfully obtain the lock, we know that it will
-        * automatically be released when the process exits (which will happen
-        * after we call server_execve()).
-        */
-       if (child_alock_fd != -1) {
-               if (flock(child_alock_fd, LOCK_SH | LOCK_NB) == -1) {
-                       if (alock_errmsg_len != 0)
-                               (void) write(r->client_socket,
-                                   CONF.ALOCK_ERRMSG, alock_errmsg_len);
-                       syslog(LOG_NOTICE,
-                           "Closing request to [%s] (ALOCK locked)",
-                           r->client_address_name);
-                       /* End current request immediately */
-                       server_close();
-               }
-       }
-
-       if (CONF.RLIMITS && rlimit_security() == -1)
-               return;
-
-       if (CONF.EXECUTABLE_SECURITY && executable_security(command) == -1)
-               return;
-
-       (void) server_execve(command, (char * const *)command_argv, NULL);
-       /* NOTREACHED */
-}
diff --git a/mmsoftware/mmspawnd2/mmspawnd.conf.5 b/mmsoftware/mmspawnd2/mmspawnd.conf.5
deleted file mode 100644 (file)
index 3a4f438..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-.\" $Id: mmspawnd.conf.5,v 1.1 2005/11/17 13:32:24 mmondor Exp $
-.\"
-.\" Copyright (C) 2003, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\" 5. Redistribution of source code may not be released under the terms of
-.\"    any GNU Public License derivate.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd October 28, 2003
-.Dt MMSPAWND.CONF 5
-.Os mmsoftware
-.Sh NAME
-.Nm mmspawnd.conf
-.Nd
-.Xr mmspawnd.conf 5
-configuration file for
-.Xr mmspawnd 8
-.Sh DESCRIPTION
-The
-.Nm /usr/local/etc/mmspawnd.conf
-file may contain one or more keyword/value pairs per line, empty lines or
-comments.  A ';' or '#' character causes all other characters to be considered
-as a comment, and to be ignored, until the end of the current line. It is
-very important to enclose the value for a keyword in double quotes ('"'
-characters) if the following characters are found in it: ';', '#', space and
-tab. It is allowed to use an equal sign '=' between the keyword name and it's
-argument. Here are documented the various possible keywords and their
-allowed values, as well as their defaults.
-.Pp
-.Ss Service administration parameters
-.Pp
-.Bl -tag -width indent -offset indent
-.It Nm CHROOT_DIR Ar "directory"
-If specified and non-empty, causes the daemon to use
-.Xr chroot 2
-at initialization so that it becomes jailed into the wanted alternative root
-directory. Obviously, all required files for the application should have a copy
-within the new root (this may include files such as
-.Nm /etc/resolv.conf ,
-.Nm /etc/hosts ,
-.Nm /etc/passwd ,
-.Nm /etc/group ,
-a few shared libraries, the executable binary to be launched, and so on,
-as required by the application and libc.
-.It Nm LOCK_PATH Ar "fullpath"
-Specifies the location where the internal synchronization (and anti-recursive
-runlock) are to be created (before chrooting). Should consist of an absolute
-full pathname including a filename, after which will automatically be postfixed
-extensions for the various locks.
-When several server instances are run concurrently to serve multiple services,
-the name of the lock files should be different for each to not conflict.
-.It Nm PID_PATH Ar "fullpath"
-Tells where to store the file holding the server process ID to be killed with
-.Dv SIGTERM
-(sig 15) to cause the server to cleanly exit. This is done before chrooting.
-When several server instances are run concurrently to serve multiple services,
-the name of the PID files should be different for each to not conflict.
-.It Nm ALOCK_PATH Ar "fullpath"
-If specified and non-empty, this enables a special feature of
-.Nm mmspawnd
-which allows advisory locking to be used on a special file with third
-party applications to synchronize with the service. This obviously should
-be configured with care, but is most useful with some setups. The file
-will be created before calling
-.Xr chroot 2
-and thus anywhere wanted on the filesystem.
-.Pp
-When this facility is enabled,
-.Nm mmspawnd
-uses
-.Xr flock 2
-to obtain an exclusive advisory lock on that file whenever one or more
-connections exist, still being served by the service. This means that
-whenever another application is allowed to obtain the lock using the
-same manner (it should also use exclusive mode), no clients are connected
-anymore to the service, and the other application may be allowed to safely
-perform special operations which requires the service to be busy. For as long
-as the file remains locked by the third party application, the
-.Nm mmspawnd
-server will refuse connections from any users (it will in fact accept them
-but immediately drop the connection without running the service). As soon
-as the other application releases back the lock, normal operation is resumed.
-.Pp
-.Xr mmanoncvs 8
-for instance uses this feature during the short amount of time required for
-two rename(2) operations to update the public cvs pserver read-only repository.
-It is very important to make sure that permissions are properly set on the
-lock file when using this feature, to only enable the wanted application to
-obtain the lock (which requires at least read access to the file). See
-the few next options to do this.
-.It Nm ALOCK_USER Ar "user"
-When the
-.Nm ALOCK_PATH
-is set, enabling the alock feature, this specifies the user which should be
-set to be the owner of the lock file.
-.It Nm ALOCK_GROUP Ar "group"
-When the alock feature is enabled, tells which group should be set for the lock
-file.
-.It Nm ALOCK_MODE Ar "mode"
-To be used when the alock feature is enabled. Specifies the permission mode
-bits to apply to the lock file, so that only the intended application can use
-it.
-.It Nm USER Ar "user"
-At server initialization, it drops privileges from the superuser to the
-specified user, definitively. This can be specified as either a username
-or it's user ID number.
-.It Nm GROUPS Ar "group,..."
-When dropping privileges, the process will become part of these groups.
-More than one group may be specified, by name or ID, separated by commas,
-without spaces. The first group will be set to the real process group, and
-others as secondary access ones.
-.It Nm LOG_FACILITY Ar "facility"
-Syslog facility which should be used for error logging. Should normally be
-one of
-.Dv LOG_AUTH , LOG_AUTHPRIV , LOG_CRON,  LOG_DAEMON ,
-.Dv LOG_FTP , LOG_KERN , LOG_LPR , LOG_MAIL ,
-.Dv LOG_NEWS , LOG_SYSLOG , LOG_USER
-or
-.Dv LOG_UUCP .
-See
-.Xr syslog 3
-man page for more information.
-.It Nm COMMAND Ar "command"
-Specifies the command which should be executed for each client which will
-be served. There can be as many command line arguments as
-.Nm MAX_ARGUMENTS
-allows. The path to the executable to launch should be absolute. No globbing
-or substitution of any kind is done on the arguments. It is allowed to
-delimit arguments containing spaces or tabs into single quotes (').
-.It Nm MAX_ARGUMENTS Ar "number"
-This parameter sets the maximum allowed number of command line parameters which
-can be passed to the application in
-.Sy COMMAND .
-.It Nm PROCTITLE Ar "string"
-This is useful if multiple services are served using
-.Xr mmspawnd 8
-for commands such as
-.Xr ps 1 ,
-notably on BSD systems. Where available, this causes the supplied string
-to prefix the comments attached to the processes using
-.Xr setproctitle 3 .
-It also is appended to the daemon name for
-.Xr syslog 3
-at
-.Xr openlog 3
-time.
-.El
-.Ss TCP server administration
-.Bl -tag -width indent -offset indent
-.It Nm LISTEN_ADDRESSES Ar "address ..."
-Tells to which interfaces the server should listen to, separated by spaces.
-The arguments should be enclosed in double quotes if more than one address
-is supplied. These addresses are used for
-.Xr bind 2 .
-Specifying "0.0.0.0" causes
-.Nm mmspawnd
-to listen to all interfaces.
-.It Nm LISTEN_PORT Ar "number"
-Supplies which TCP port number to listen to. This must be a numeric port number
-within the range of 1 to 65535.
-.It Nm MAX_CONNECTIONS Ar "number"
-The maximum number of simultaneous clients which should be served at once.
-.It Nm MAX_ADDRESSES Ar "number"
-The maximum number of simultaneous different client IP addresses to serve.
-.It Nm MAX_PER_ADDRESS Ar "number"
-The maximum number of simultaneous clients to serve at once per IP address.
-.It Nm CONNECTION_RATE Ar "number"
-The maximum number of connections to accept from each address within
-.Nm CONNECTION_PERIOD .
-Can be 0 to disable connection rate throttling.
-.It Nm CONNECTION_PERIOD Ar "number"
-If
-.Nm CONNECTION_RATE
-is non-zero, specifies the number of seconds during which a maximum of
-.Nm CONNECTION_RATE
-connections are to be allowed.
-.It Nm RESOLVE_ADDRESSES Ar "boolean"
-Specifies weither client addresses should be resolved to hostnames when
-logging the connection event via
-.Xr syslog 3 .
-An internal cache is maintained for recently connected addresses for faster
-performance. This is done in the child serving process so that it does not
-slow down the listener process responsible for accepting new connections.
-Should be TRUE or FALSE.
-.El
-.Ss Application security limits
-.Bl -tag -width indent -offset indent
-.It Nm COMMAND_TIMEOUT Ar "seconds"
-Specifies the maximum number of seconds allowed for complete execution of
-.Nm COMMAND .
-If the command does not terminate before this number of seconds elapse, it
-is forcefully killed using the
-.Dv SIGTERM
-signal. Beware to put this limit high enough so that it does not interfere
-with normal service operation. This feature however allows to get rid of
-eternally idle or frozen sessions.
-.Pp
-Eventually, support for network inactivity timeout, as well as bandwidth
-shaping/throttling will be added. However, since those require a new design
-and a rewrite of
-.Xr mmspawnd 8 ,
-this is the best we can do for now. (This behavior is still better than
-.Xr inetd 8 ,
-however). We also ensure to set the
-.Dv SO_KEEPALIVE
-option on the client descriptors to better recognize connection problems and
-act accordingly to stop the process.
-.It Nm RLIMITS Ar "boolean"
-If TRUE, all following
-.Nm RLIMIT_*
-parameters will be applied to the children processes before launching the
-application command if they are not set to -1 values.
-.Xr setrlimit 2
-is called to perform this. Note that these should be set to sane values
-for proper function, by a competent administrator, if this option is
-enabled. When disabled, or if enabled but for each following option specified
-with -1, the defaults are used, which are inherited from the server process.
-.Bl -tag -width indent -offset indent
-.It Nm RLIMIT_CORE Ar "value"
-If not -1, the largest size (in bytes) core file that may be created.
-.It Nm RLIMIT_CPU Ar "value"
-If not -1, The maximum amount of cpu time (in seconds) to be used by
-each process.
-.It Nm RLIMIT_DATA Ar "value"
--1 or The maximum size (in bytes) of the data segment for a process;
-this defines how far a program may extend its break with the
-.Xr sbrk 2
-or
-.Xr mmap 2
-system calls.
-.It Nm RLIMIT_FSIZE Ar "value"
-The largest size (in bytes) file that may be created, or -1.
-.It Nm RLIMIT_MEMLOCK Ar "value"
-The maximum size (in bytes) which a process may lock into physical memory
-(wire) using the
-.Xr mlock 2
-system call function, or -1.
-.It Nm RLIMIT_NOFILE Ar "value"
-If not -1, the maximum number of open files for this process.
-.It Nm RLIMIT_NPROC Ar "value"
-The maximum number of simultaneous processes for this user ID, or -1.
-.It Nm RLIMIT_RSS Ar "value"
-The maximum size (in bytes) to which a process's resident
-set size may grow.  This imposes a limit on the amount of
-physical memory to be given to a process; if memory is
-tight, the system will prefer to take memory from processes
-that are exceeding their declared resident set size.
--1 to use the defaults.
-.It Nm RLIMIT_STACK Ar "value"
-If not -1, the maximum size (in bytes) of the stack segment for a
-process; this defines how far a program's stack segment
-may be extended.  Stack extension is performed automatically by the system.
-.El
-.El
-.Ss Debugging support
-.Bl -tag -width indent -offset indent
-.It Nm STDERR_FILE Ar "fullpath"
-By default, the standard error stream (stderr) of
-.Nm COMMAND
-is redirected to the "/dev/null" device. However, it may be nice to be able
-to obtain those messages from time to time, or to see if any are generated
-by the application. This option, if non-empty, creates, or appends to the
-specified file (outside of the chroot setup). This option should not be
-used on production systems, as the file will grow without bounds. If a log
-rotation system is used,
-.Xr mmspawnd 8
-will require to be restarted everytime it is ran. It is merely for debugging.
-.El
-.Sh DEFAULTS
-The following defaults are used:
-.Pp
-.Bd -literal -offset indent
-CHROOT_DIR             ""
-LOCK_PATH              "/var/run/mmspawnd.lock"
-PID_PATH               "/var/run/mmspawnd.pid"
-ALOCK_PATH             ""
-ALOCK_USER             "mmspawnd"
-ALOCK_GROUP            "mmspawnd"
-ALOCK_MODE             "400"
-USER                   "mmspawnd"
-GROUPS                 "mmspawnd"
-LOG_FACILITY           "LOG_AUTHPRIV"
-COMMAND                        "/sbin/nologin"
-MAX_ARGUMENTS          16
-PROCTITLE              ""
-
-LISTEN_ADDRESSES       "127.0.0.1"
-LISTEN_PORT            2323
-MAX_CONNECTIONS                32
-MAX_ADDRESSES          32
-MAX_PER_ADDRESS                1
-CONNECTION_RATE                5
-CONNECTION_PERIOD      30
-RESOLVE_ADDRESSES      FALSE
-
-COMMAND_TIMEOUT                300
-RLIMITS                        FALSE
-RLIMIT_CORE            -1
-RLIMIT_CPU             -1
-RLIMIT_DATA            -1
-RLIMIT_FSIZE           -1
-RLIMIT_MEMLOCK         -1
-RLIMIT_NOFILE          -1
-RLIMIT_NPROC           -1
-RLIMIT_RSS             -1
-RLIMIT_STACK           -1
-
-STDERR_FILE            ""
-.Ed
-.Sh AUTHOR
-.Nm mmspawnd
-was written by Matthew Mondor, and is
-Copyright (c) 2003, Matthew Mondor, All rights reserved.
-.Sh FILES
-.Bl -tag -width indent -offset indent
-.It Pa /usr/local/etc/mmspawnd.conf
-This file
-.It Pa /usr/local/sbin/mmspawnd
-The
-.Xr mmspawnd 8
-server binary itself.
-.El
-.Sh SEE ALSO
-.Xr mmspawnd 8 ,
-.Xr syslog 3 ,
-.Xr openlog 3 ,
-.Xr chroot 2 ,
-.Xr bind 2 ,
-.Xr setrlimit 2 ,
-.Xr ps 1 ,
-.Xr setproctitle 3 .
-.Sh BUGS
-Not really a bug, but tied to each interface could be most connection control
-options.
-.Pp
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/mmstatd/ChangeLog b/mmsoftware/mmstatd/ChangeLog
deleted file mode 100644 (file)
index fe9850c..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-$Id: ChangeLog,v 1.21 2005/11/17 07:38:07 mmondor Exp $
-
-
-
-Release: mmstatd 0.0.9 devl
-Date   : November 17, 2005
-By     : Matthew Mondor
-
-* Bug fixes
-  - Although the documentation in mmstatd.conf(5) specified that 0 could be
-    specified to STATS_RATE to disable connection rate throtling for statistic
-    requests, the configuration file parser forced a minimum value of 1. Fixed
-  - A free() bug was found in mmpool(3)'s pool_free().
-  - The old string library which had functions copied as-is from my old code
-    of the 80's was througly revised. Many functions were either rewritten or
-    modified for better style and performance. Moreover, all library functions
-    have been throughly tested using a program especially made to test them.
-    A bug in mm_memcmp() and one in mm_memmove() were fixed along the way.
-* Reliability enhancement
-  - Although mmstatd(8) always verified the error status of fwrite(3) calls
-    when synchronizing it's database, it now also calls fsync(2) after
-    fflush(3) before closing it, and verifies for the success of both fsync(2)
-    and close(2).
-  - Just as before, this is done on a temporary file, which is either
-    discarded on error, or which atomically replaces the old database
-    with rename(2) if everything was successful. Because stdio uses buffering
-    and that actual database sync was not guaranteed by fflush(3) unless
-    fsync(2) was successfully used, the new behavior should be safer.
-* Performance enhancements
-  - The configuration file parser was rewritten to be more efficient and
-    to hold cleaner code than the previous one which was migrated from
-    one of my first C programs many years ago :) The configuration files
-    format is now more flexible as well, although the current files will
-    parse properly without modifications still.
-  - The mmstat(8) utility now uses full buffering when writing to stdout
-    and stderr for performance (stdio defaults to line-buffered streams which
-    caused a write(2) system call to occur per line, and is thus unefficient).
-  - mmpool(3) was reimplemented for better efficiency. Also was added support
-    for object constructor/destrutor functions, but which are not currently
-    used by this application.
-* New features
-  - Both crash recovery log files and the database saving format are now
-    platform-independent as well as architecture-independent. This means that
-    byte order convertions to network byte order are performed for writing,
-    and convertions are made back to host byte order when reading. It also
-    means that all elements are written with a platform-independent fixed
-    sized format (i.e. u_int64_t for off_t, even on platforms where off_t is
-    32-bit, u_int32_t for time_t and uid_t, etc).
-    This means that mmstatd(8) files can be stored via NFS and used by another
-    architecture or platform client, and that if moving the database and logs
-    to another architecture while upgrading the network or such, that their
-    format will be valid for use on the other system.
-    All older database formats are recognized and automatically converted when
-    mmstatd(8) is launched. However, this is not true for log files. This
-    means that prior to upgrading, you should cleanly kill, restart mmstatd(8)
-    and kill it again to ensure that all recovery logs have been processed and
-    flushed. This can be seen by an only log file named 00000000.log of 0
-    bytes. It is then safe to upgrade mmstatd(8) and to run the new version.
-    It is however still recommended to backup the mmstatd.db file first, in
-    case of failure to convert it properly.
-    Client programs will also need to be recompiled nevertheless, since the
-    log_entry structure and unions have been modified to use
-    platform-independent sized elements, requireing internal modifications to
-    the mmstat(3) client library.
-* Other
-  - BSD-style mdoc manual pages were enhanced.
-  - The mmlimitrate(3) library was written to restrict the amount of code
-    duplication among my various software which require rate limiting in
-    various situations. The software now uses this API for rate throttling
-    (except the bandwidth shaping which is handled by mmfd(3)).
-
-
-
-Release: mmstatd 0.0.8 devl
-Date   : July 1, 2003
-By     : Matthew Mondor
-
-* Bug fixes
-  - Although unlikely to occur, the underlaying mmhash(3) library comported
-    a bug which could cause the key rotation to force a table rehash during
-    an iteration. This could cause some matching keys to not be processed.
-    Both hashtable_unlink() and hashtable_link() will now refrain from
-    causing table rehashes when called from within an iteration for safety.
-  - Some annoying debugging printf(3) was removed from the mmstat(8) client,
-    it was left out as part of a previous test.
-  - When alot of mmstat() operations were performed into a transaction using
-    mmstat_transact(), it was possible to exceed the maximum allowed message
-    size for the socket transmition to the mmstatd(8) server. We now use
-    4.2BSD setsockopt(2) in both mmstat(3) client API and mmstatd(8) to set
-    the size of the socket buffer to fix this problem.
-* Other
-  - The mmstat(3) key names were modified to be '|' separated rather than
-    '.' separated. Although I have been trying to avoid such a change which
-    obviously requires fixing alot of scripts I am using, it was proven with
-    time that the '.' character was too widely used and that '|' was ideal
-    as a replacement. It is not hard to use a script to use the mmstat(8)
-    reset command and convert all old entries to the new type if necessary.
-    As a result, filenames which comport '.' characters for which counters
-    are maintained are much better to handle and to isolate. The same applies
-    to IP addresses. This in itself did not require any changes to the
-    mmstat software, but mmstat(3) and mmstatd(8) users should be aware of
-    this.
-  - apache-mmstat(8) utility was added as an mmstat(3) backend for apache
-    httpd(8).
-* Important
-  - The maximum key name length now was bumped from 128 to 256 bytes. As
-    a result, a special log file synchronization will be required as was
-    the case for mmstatd 0.0.7 upgrade. This also requires mmstat clients
-    using the mmstat(3) API to be recompiled. See the ChangeLog notes on
-    mmstatd 0.0.7 release about this synchronization issue when upgrading.
-  - The maximum number of protected mmstat() calls within an mmstat_transact()
-    transaction has been bumped from 16 to 32. This requires recompilation of
-    mmstat(3) clients and server.
-
-
-
-Release: mmstatd 0.0.7 devl
-Date   : June 19, 2003
-By     : Matthew Mondor
-
-* Important
-  - The recovery log format has changed. This means that when upgrading,
-    you should first make sure that your actual database is in sync.
-    There are two ways to do this a) kill mmstatd using SIGTERM and
-    restart it again, or b) perform any rotation operation, which forces a
-    full sync. You can then kill mmstatd and upgrade it. Failure to follow
-    these instructions may result in mmstatd crashing, and yielding undefined
-    behavior. Moreover, both mmstat clients (the shell standard mmstat client,
-    as well as any other application using the mmstat(3) interface, and the
-    mmstatd server need to be recompiled when upgrading.
-  - MMSTAT, MMSTATENT and MMSTATRES data types were changed to mmstat_t,
-    mmstatent_t and mmstatres_t for consistency with other mmsoftware style.
-    This will require minor modifications to software using the mmstat(3) API.
-  - The GROUPS directive now expects groups to be comma-separated instead of
-    space-separated. The quotes then of course also become optional if multiple
-    groups are specified. This was made because that mmreadcfg(3) library is
-    also used by other of my projects for which comma-separated groups were
-    required.
-* Performance enhancement
-  - The system used to hold the keys into a sequencial linked list using a
-    64-bit hash coupled with the key strings to make the list lookup faster.
-    Although this worked fine and was ideal for very small sets, it would
-    become a bottleneck for the librarian process when in heavy use with
-    a very large number of entries. It now uses a 32-bit string hash function,
-    but also a bucket-based hashing algorithm to store the entries which
-    provides fast indexing, considerably speeding up lookups. Moreover, the
-    32-bit string hashing function collisions will not cause storage
-    collisions and is faster than the 64-bit one used to be on 32-bit systems.
-    The mmhash(3) library is used for this, which was imported from my
-    Xisop project.
-* Bug fixes
-  - The default shell mmstat client would always force autoflush on updates
-    even if the 'a' flag was not specified.
-  - Because full disk database synchronization happen rarely, when mmstatd
-    is stopped and restarted, if alot of recent modifications were made which
-    are in the recover logs, their modification timestamps would only be
-    considered when recovering from those logs at mmstatd startup. The time
-    of each operation is now stored within the logs as well, so that at
-    recovery be applied the real modification time to the affected keys.
-
-
-
-Release: mmstatd 0.0.6 devl
-Date   : January 9, 2003
-By     : Matthew Mondor
-
-* Bug fix
-  - Delete operations performed on unexisting keys would crash the daemon,
-    this was fixed.
-* New features
-  - mmstat_init() was modifed in a way that autoflush keys (which delete
-    themselves automatically when reaching zero) can now consist of both
-    volatile or persistant keys.
-  - The various STAT_RESET, STAT_UPDATE and STAT_DELETE operations can
-    now be atomically performed on all keys matching a supplied '*' and '?'
-    wildcard pattern as well.
-  - The mmstat(8) utility now supports 'hreport' which reports more readable
-    results for humans (although less verbose).
-  - If compiled with -DNODROPPRIVS it will not attempt to perform any
-    credential changes before launching. In which case it will also refuse
-    to be started by the superuser. Userful for non-privileged users.
-  - The mmstatd, mmstat(3) library and as such mmstat(8) utility will now use
-    the MMSTATCONF environment variable if set to determine which configuration
-    file to use. This permits several non-privileged users to each run their
-    own mmstat service for instance.
-  - mmstatd can now be specified configuration file to use on the command
-    line arguments.
-
-
-
-Release: mmstatd 0.0.7 devl
-Date   : April 25, 2003
-By     : Matthew Mondor
-
-* Minor interface change
-  - MMSTAT, MMSTATENT and MMSTATRES data types were changed to mmstat_t,
-    mmstatent_t and mmstatres_t for consistency with other mmsoftware style.
diff --git a/mmsoftware/mmstatd/GNUmakefile b/mmsoftware/mmstatd/GNUmakefile
deleted file mode 100644 (file)
index cfabd2d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# $Id: GNUmakefile,v 1.4 2004/06/01 23:52:43 mmondor Exp $
-
-MMLIB_PATH := ../mmlib
-
-MMLIBS := $(addprefix ${MMLIB_PATH}/,mmarch.o mmpool.o mmlog.o mmreadcfg.o \
-mmstring.o mmhash.o mmstat.o mmlimitrate.o)
-OBJS := $(addprefix src/,mmstatd.o mmstat.o)
-BINS := $(addprefix src/,mmstatd mmstat)
-CFLAGS += -Wall
-
-all: $(BINS)
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I${MMLIB_PATH} -Isrc -o $@ $<
-
-
-src/mmstatd: $(MMLIBS) src/mmstatd.o
-       cc -o $@ src/mmstatd.o -lc $(MMLIBS)
-
-src/mmstat: $(MMLIBS) src/mmstat.o
-       cc -o $@ src/mmstat.o -lc $(MMLIBS)
-
-
-install: all
-       install -cs -o 0 -g 0 -m 500 src/mmstatd /usr/local/sbin
-       install -cs -o 0 -g 0 -m 550 src/mmstat /usr/local/sbin
-       install -c -o 0 -g 0 -m 444 src/mmstatd.conf.5 /usr/local/man/man5
-       install -c -o 0 -g 0 -m 444 src/mmstat.8 /usr/local/man/man8
-       install -c -o 0 -g 0 -m 444 src/mmstatd.8 /usr/local/man/man8
-       install -c -o 0 -g 0 -m 444 ../mmlib/mmstat.3 /usr/local/man/man3
-
-
-clean:
-       rm -f $(BINS) $(OBJS) $(MMLIBS)
diff --git a/mmsoftware/mmstatd/README b/mmsoftware/mmstatd/README
deleted file mode 100644 (file)
index c797aa6..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-$Id: README,v 1.3 2003/06/19 15:03:29 mmondor Exp $
-
-MMSTATD(8)              NetBSD System Manager's Manual              MMSTATD(8)
-
-NAME
-     mmstatd - Statistics librarian and logger daemon with recovery and trans-
-     action support
-
-SYNOPSIS
-     mmstatd [config_file]
-
-DESCRIPTION
-     mmstatd consists of a statistics librarian daemon used by the familly of
-     mm utilities (mmmail, mmftpd, etc). It simply allows applications to
-     record statistical information using a key-based system. It also supports
-     transactions and crash recovery logging. Moreover, it features volatile
-     and consistant database entries, with creation and modification times-
-     tamps.
-
-     The main reason why I wrote it was because syslog does not consist of an
-     ideal approach to count statistics, and that using an SQL server for this
-     is overkill, especially with required SQL commands parsing and atomic-
-     safe transaction locks. db4 could have been more efficient, but it is
-     quite easy to rival with it according to size. The size of mmstatd and
-     mmstat library is very small, and it's performance is decent. Moreover a
-     database server would consider all keys as persistant storage, when a re-
-     quirement for both persistant and volatile ones was met.
-
-     The way it works
-
-     Basically, it starts up two asynchroneous processes, the librarian and
-     logger.
-
-     The librarian is responsible for managing the database and affecting
-     changes while asynchroneously reading available logs. It also permits ob-
-     tention of statistics report connecting to a Unix domain stream socket.
-     The librarian synchronizes the memory database to disk every once in a
-     while, recording the current position in the logs, and deleting obsolete,
-     already synchronized logs when required. This synchronization to disk is
-     only performed at large time intervals, to minimize CPU and drive load,
-     and maximise responsiveness.  The librarian also establishes a listening
-     UNIX stream socket, to serve reports and rotation requests.
-
-     The logger, in turn, listens to a Unix datagram socket, and writes the
-     logs, syncing them to disk frequently enough, for both the librarian and
-     logger.  This allows the logs to be used for recovery of persistant modi-
-     fications that were performed since the last full database sync. More-
-     over, it permits the clients to always be able to send more packets with-
-     out being subject to the librarian processing, avoiding a bottleneck.
-
-     Every time mmstatd is started, it first ensures to run with normal user
-     privileges, then looks for recovery logs and performs necessary modifica-
-     tions to the database, before forcing a sync of the new database to disk,
-     deleting all recovery logs. It then launches the two asynchroneous pro-
-     cesses which then become ready to serve their tasks.
-
-     Using this design allows applications to use a simple syslog-like API to
-     update statistics, in a very fast manner. For the various mm daemons, it
-     serves as a who database, using volatile storage, and as various statis-
-     tical tasks using persistant storage.
-
-     The logging socket, used to send update requests, as well as the status
-     socket, are independant and can have specific permissions, so that only
-     applications who should access the service may. The user application in-
-     terface library is quite simple to use by programs wanting to keep their
-     statistics using mmstatd.  See the mmstat(3) man page for more informa-
-     tion.
-
-INSTALLATION
-     mmstatd is installed by the make.sh scripts of both mmftpd and mmmail by
-     Matthew Mondor. It's administration is made through /etc/mmstatd.conf
-     (See mmstatd.conf(5) man page) and mmstat (See mmstat(8) man page).
-
-     Here is an overview of standard permissions various files should have:
-
-           Permissions Owner    Group   File
-
-           -rwxr-x---  root     staff   /usr/local/sbin/mmstat
-           -rwx------  root     wheel   /usr/local/sbin/mmstatd
-
-           drwxr-x---  mmstatd  mmstat  /var/mmstatd
-
-           s-w--w----  mmstatd  mmstat  /var/mmstatd/mmstatd_log.sock
-           srw-rw----  mmstatd  staff   /var/mmstatd/mmstatd_stat.sock
-
-     Basically, the administrator will need access to mmstat binary as well as
-     to both /var/mmstatd/*.sock files. Applications using the mmstat(3) fa-
-     cility require access to the /var/mmstatd/mmstatd_log.sock file only. On-
-     ly uid zero should have access to /var/mmstatd directory and mmstatd dae-
-     mon.
-
-     mmstatd should normally be started before any other daemons using the
-     mmstat(3) interface. Although this is not obligatory, it is highly recom-
-     mended. As it will take the time to perform recovery before calling
-     fork(2) other daemons will have a clean and ready daemon to serve their
-     requests, so a startup script typically would use something like:
-
-           /usr/local/sbin/mmstatd
-           /usr/local/sbin/mmftpd
-           /usr/local/sbin/mmsmtpd
-           /usr/local/sbin/mmpop3d
-
-FILES
-     /etc/mmstatd.conf               This file consists of the configuration
-                                     file for mmstatd and controls all it's
-                                     configurable parameters.
-
-     /var/mmstatd                    The mmstat environment directory, where
-                                     recovery logs and database file are lo-
-                                     cated. The default configuration also
-                                     stores UNIX domain sockets there.
-
-     /var/mmstatd/mmstatd_stat.sock  The UNIX stream socket on which listens
-                                     mmstatd librarian process, used by the
-                                     administrator via mmstat binary to query
-                                     statistical reports and request key rota-
-                                     tions.
-
-     /var/mmstatd/mmstatd_log.sock   The UNIX datagram socket on which listens
-                                     mmstatd logger process, used by all ap-
-                                     plications using the mmstat(3) interface
-                                     to update statistics.
-
-     /var/mmstatd/mmstatd.db         The database file used to permanently
-                                     store persistant storage statistical
-                                     keys. When a disk synchronization occurs,
-                                     a temporary file is used to save the
-                                     database on the same filesystem, and
-                                     rename(2) is used to move it over this
-                                     file in an atomic manner.
-
-     /var/mmstatd/????????.log       Log files internally used and automati-
-                                     cally maintained by mmstatd for crash re-
-                                     covery.
-
-     /usr/local/sbin/mmstatd         The actual daemon binary documented by
-                                     mmstatd(8)
-
-     /usr/local/sbin/mmstat          The administration utility documented by
-                                     mmstat(8)
-
-ENVIRONMENT
-     MMSTATCONF  If set, specifies the absolute location of the configuration
-                 file to load instead of the default /etc/mmstatd.conf.  If a
-                 configuration file name is specified on the command line, it
-                 will override this environment variable even if it was set.
-
-AUTHOR
-     The suite of mmstat daemon, related utilities and documentation were
-     written by Matthew Mondor, and are Copyright (c) 2002-2003, Matthew Mon-
-     dor, All rights reserved.  They were developped under NetBSD 1.5.3 for
-     the mmftpd and mmmail suite of daemons from the same author.
-
-SEE ALSO
-     mmstat(3), mmstatd.conf(5), mmstat(8), rename(2), fork(2), unix(4).
-
-BUGS
-     The internal format of the log files and database file are not endian-in-
-     dependant and will therefore only remain useable on architectures using
-     the same endian format. Of course it would be possible to use mmstat(8)
-     utility to perform exportation and importation to a new system for the
-     time being.  This will eventually change and an endian-independant format
-     will be used.
-
-NetBSD 1.6_STABLE                11 Dec, 2002                                3
diff --git a/mmsoftware/mmstatd/clean.sh b/mmsoftware/mmstatd/clean.sh
deleted file mode 100755 (executable)
index 77bfe13..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-# $Id: clean.sh,v 1.2 2003/07/02 17:20:57 mmondor Exp $
-
-. ../mmlib/makefuncs.sh
-
-cd ../mmlib/
-clean mmlib
-cd ../
-
-cd mmstatd/src/
-clean mmstatd
-cd ../../
-
-cd apache-mmstat/
-clean apache-mmstat
-cd ../
diff --git a/mmsoftware/mmstatd/etc/mmstatd.conf b/mmsoftware/mmstatd/etc/mmstatd.conf
deleted file mode 100644 (file)
index 0fe9a44..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-# $Id: mmstatd.conf,v 1.3 2004/02/15 16:56:22 mmondor Exp $
-
-# This consists of the configuration file used by both mmstatd service
-# and mmstat library initialization. See mmstatd.conf(5) man page for details.
-
-
-
-# User mmstatd should run as (usually mmstatd)
-USER           mmstatd
-# Groups mmstatd should be part of, separated by commas
-# LOG_GROUP and STAT_GROUP should be specified here as well
-GROUPS         mmstat,staff
-
-
-
-# syslog facility which should be used
-LOG_FACILITY   LOG_AUTHPRIV
-
-
-
-# Location where mmstatd writes it's pid file
-PID_FILE       "/var/mmstatd/mmstatd.pid"
-#
-# Location of mmstatd lock file, this is only used to make sure that only  
-# one copy of the service is running, otherwise this could lead to database
-# corruption
-LOCK_FILE      "/var/mmstatd/mmstatd.lock"
-#
-# Location of statistics update request socket
-LOG_SOCKET     "/var/mmstatd/mmstatd_log.sock"
-#
-# Location of statistics report request socket
-STAT_SOCKET    "/var/mmstatd/mmstatd_stat.sock"
-#
-# Location where database and recovery logs are stored
-ENV_DIR                "/var/mmstatd"
-
-
-
-# LOG_SOCKET is created with mode 220. This permits users of the following
-# specified group to perform statistic update requests.
-LOG_GROUP      mmstat
-#
-# STAT_SOCKET is created with mode 660. This permits users of the following
-# specified group to obtain statistic reports.
-STAT_GROUP     staff
-
-
-
-# Specifies the interval in seconds at which the statistics db will be
-# synchronized to disk. This delay can be long enough, as a good log-based
-# recovery technique is used in case system crashed between two sync events.
-SYNC_INTERVAL  1800
-#
-# Maximum number of bytes to write to recovery logs before forcing a sync
-# with physical media (using fsync()). 0 Can be specified to force a sync
-# after every new entry; Higher values may cause some of the last update
-# requests before a crash to be lost but will be more efficient.
-SYNC_BYTES     4096
-#
-# Maximum size of a recovery log file. When reaching that size internal
-# rotation to other files is performed. Logs are internally maintained
-# and cleaned up as necessary by mmstatd and are not user serviceable.
-MAX_LOGSIZE    1048576
-#
-# Maximum rate to accept statistic report requests at. This # prevents an
-# application from requesting a large number of full reports thus potentially
-# preventing the librarian part of mmstatd to peform it's # vital tasks. As a
-# general rule reports are not requested frequently. Care should be taken to
-# choose an adequate STAT_GROUP to restrict access also. STATS_RATE specifies
-# maximum number of requests to accept in STATS_TIME seconds.
-STATS_RATE     0               STATS_TIME      10
diff --git a/mmsoftware/mmstatd/future.txt b/mmsoftware/mmstatd/future.txt
deleted file mode 100644 (file)
index 064857b..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-We could either use xdr(3) to keep a binary format, but we also optionally
-could fallback to text formats (which actually also would allow other programs
-to easily work with the format using simple scripts). The adventage of a text
-format is that it is endian-independant. A disadventage is that more CPU time
-is required; We need to convert the internal binary representation to an
-ASCII text form, and need to convert that ASCII format to internal binary
-numbers again.
-
-If using xdr(3), we should still change the current format to not use
-sizeof(off_t) (which appears to be 32-bit on i386 Linux, while 64-bit on BSD).
-We instead should map the off_t type to an internal u_int64_t representation
-and then save that one instead.
-
-
-
-Database file format:
-
-5      (version)
-0      (lognum)
-20493  (logpos)
-(value) (created) (modified) (uid) (key)
-33 1057972228 1066870567 0 mmmail|box|mmondor@gobot.xisop|messages-out
-3090 1057972167 1066870567 0 mmpop3d|total|bytes-in
-(etc)
-
-
-
-Logentry format:
-
-TRANSACT (begin)1
-TRANSACT (begin)0 (commit/rollback)1
-NEWFILE 1 (lognum)
-UPDATE (time)1066870567 (persistant)1 (autoflush)1 (modifier)1 (key)mmpop3d|total|bytes-in
-RESET (time)1066870567 (persistant)1 (autoflush)1 (value)0 (key)mmpop3d|total|bytes-in
-DELETE (persistant)1 (key)mmpop3d|total|bytes-in
-
-
-
-Report format:
-
-(persistant) (value) (created) (modified) (uid) (key)
-1 33 1057972228 1066870567 0 mmmail|box|mmondor@gobot.xisop|messages-out
-1 3090 1057972167 1066870567 0 mmpop3d|total|bytes-in
-
-
-
-It might be useful to add support for namespaces. It then would also be
-possible to use simple authentication to the daemon for clients to be
-able to perform modifications. If this was done using a stream rather
-than datagrams, we then could also support fair remote service.
-Look into libio and libevent so that the logger daemon could support a
-wide range of persistant connections. I also could add optional rc4 support...
-Unfortunately, all this would slow the system a little on the client side.
-Using blocking writes to a stream would sometimes cause a delay, and using
-unblocking writes would still cause looping as long as EAGAIN is issued...
-It perhaps would be possible for the client side to keep a buffer for speed
-and flush it as it can asynchroneously. However, this could possibly degrade
-the service reliability (atomic transactions reliability?) also, what would
-happen if the TCP connection is stalled? Would EAGAIN always be issued and
-the buffer fill? If so, what should we do? Cause the process to sleep until
-it can send the data? This has potentially more drawbacks than it sounds.
-Or, should we keep using unreliable datagrams and not care about possible
-problems, except about transaction respect?
-
-It is generally not a problem to have to perform conversions when reading
-or writing the database. It also might be convenient so that the format
-be easily manipulable by the administrator. However, the internal storage
-such as recovery logs and report format would better be implemented using
-a binary format like we use now, although an effort should be made to
-make the format endian-independant.
diff --git a/mmsoftware/mmstatd/install.sh b/mmsoftware/mmstatd/install.sh
deleted file mode 100755 (executable)
index cd5bc23..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-#!/bin/sh
-# $Id: install.sh,v 1.6 2003/10/23 01:01:32 mmondor Exp $
-
-if [ "$1" = "help" ]; then
-       echo
-       echo 'You can optionally set the following environment variables'
-       echo 'to customize the installation process. For each is shown an'
-       echo 'example using the default value followed by a breif description.'
-       echo
-       echo 'export MMLAUNCH="TRUE"'
-       echo '   Tells the install process to immediately launch the daemon(s)'
-       echo '   They are automatically killed before the binaries are copied'
-       echo '   over the old ones as is necessary with some systems. The'
-       echo '   default is to not start them back automatically.'
-       echo
-       echo 'export MMPREFIX="/usr/local"'
-       echo '   Allows to set the installation base directory. All files but'
-       echo '   configuration ones will be installed in directories relative'
-       echo '   to this one.'
-       echo
-       echo 'export MMCONFDIR="/etc"'
-       echo '   Directory in which configuration files should be stored.'
-       echo
-       echo 'export MMDEFAULTUSER="0"'
-       echo '   User new files and directories should be owned by, using'
-       echo '   user id or name.'
-       echo
-       echo 'export MMDEFAULTGROUP="0"'
-       echo '   Group new files and directories should be under, using id'
-       echo '   or name.'
-       echo
-       echo 'export MMADMINGROUP="staff"'
-       echo '   The administrators group, these can for instance view and the'
-       echo '   rotate mmstat statistics and execute mmpasswd. Will be'
-       echo '   created automatically if necessary.'
-       echo
-       echo 'export MMSTATDIR="/var/mmstatd"'
-       echo '   The directory in which mmstatd will store the stats database'
-       echo '   and log files.'
-       echo
-       echo 'export MMSTATDUSER="mmstatd"'
-       echo '   The user mmstatd will run under, to be automatically created.'
-       echo
-       echo 'export MMSTATDGROUP="mmstat"'
-       echo '   Group the mmstatd user should be part of, automatically'
-       echo '   created.'
-       echo
-       exit
-fi
-
-# Set defaults if not set
-if [ -z "$MMLAUNCH" ]; then
-       export MMLAUNCH='FALSE'
-fi
-if [ -z "$MMPREFIX" ]; then
-       export MMPREFIX='/usr/local'
-fi
-if [ -z "$MMCONFDIR" ]; then
-       export MMCONFDIR='/etc'
-fi
-if [ -z "$MMDEFAULTUSER" ]; then
-       export MMDEFAULTUSER='0'
-fi
-if [ -z "$MMDEFAULTGROUP" ]; then
-       export MMDEFAULTGROUP='0'
-fi
-if [ -z "$MMADMINGROUP" ]; then
-       export MMADMINGROUP='staff'
-fi
-if [ -z "$MMSTATDIR" ]; then
-       export MMSTATDIR='/var/mmstatd'
-fi
-if [ -z "$MMSTATDUSER" ]; then
-       export MMSTATDUSER='mmstatd'
-fi
-if [ -z "$MMSTATDGROUP" ]; then
-       export MMSTATDGROUP='mmstat'
-fi
-
-. ../mmlib/makefuncs.sh
-
-instgroup $MMADMINGROUP
-
-cd ../mmlib/
-instman mmlist.3 3
-instman mmpool.3 3
-instman mmstat.3 3
-instman mmhash.3 3
-cd ../
-cd apache-mmstat/
-instman apache-mmstat.8 8
-cd ../
-
-cd mmstatd/src/
-instuser $MMSTATDUSER $MMSTATDGROUP
-killbin mmstatd
-instbin mmstatd 700
-instbin mmstat 750 $MMADMINGROUP
-instman mmstat.8 8
-instman mmstatd.8 8
-instman mmstatd.conf.5 5
-instman mmlist.3 3
-instman mmpool.3 3
-instman mmhash.3 3
-instman mmlimitrate.3 3
-cd ../etc/
-instconf mmstatd.conf 640 $MMSTATDGROUP
-instdir $MMSTATDIR 750 $MMSTATDUSER $MMSTATDGROUP
-if [ "$MMLAUNCH" = "TRUE" ]; then
-       startbin mmstatd $MMCONFDIR/mmstatd.conf
-fi
-cd ../../
-cd apache-mmstat/
-instbin apache-mmstat 700
-
-echo
-echo "*** Please read the following man pages ***"
-echo
-echo "mmstat(8), mmstatd(8), mmstatd.conf(5), apache-mmstat(8)"
-echo "source auditors: mmstat(3), mmlist(3), mmpool(3), mmhash(3),"
-echo "                 mmlimitrate(3)"
-echo
-echo "Thank you for using mmsoftware."
-echo
diff --git a/mmsoftware/mmstatd/make.sh b/mmsoftware/mmstatd/make.sh
deleted file mode 100755 (executable)
index d846943..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-# $Id: make.sh,v 1.2 2003/07/02 17:20:57 mmondor Exp $
-
-. ../mmlib/makefuncs.sh
-
-cd ../mmlib/
-clean mmlib
-makebin mmlib
-cd ../
-
-cd mmstatd/src/
-clean mmstatd
-makebin mmstatd
-cd ../../
-
-cd apache-mmstat/
-clean apache-mmstat
-makebin apache-mmstat
-cd ../../
-
-echo
-echo 'You may now ./install.sh help or ./install.sh to install/upgrade'
-echo
diff --git a/mmsoftware/mmstatd/src/Makefile b/mmsoftware/mmstatd/src/Makefile
deleted file mode 100644 (file)
index 4ff10dc..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-# $Id: Makefile,v 1.2 2003/07/17 22:26:51 mmondor Exp $
-
-CC = gcc
-MAKE = make
-
-CFLAGS += -DDEBUG -Wall
-
-INCDIR = -I../../mmlib -I/usr/include -I/usr/pkg/include -I.
-LIBDIR = -L/usr/local/lib -L/usr/lib -L/lib -L/usr/pkg/lib
-
-LIBS = ../../mmlib/libmmondor.a -lc
-
-OBJS = mmstatd.o mmstat.o
-
-PROG = mmstatd
-PROG2 = mmstat
-
-
-CCOBJ = $(CC) $(CFLAGS) -c $(INCDIR)
-
-
-
-
-all: $(OBJS)
-       $(CC) $(CFLAGS) -o $(PROG) $(INCDIR) $(LIBDIR) $(PROG).o $(LIBS)
-       $(CC) $(CFLAGS) -o $(PROG2) $(INCDIR) $(LIBDIR) $(PROG2).o $(LIBS)
-
-
-
-
-clean:
-       -rm -f $(OBJS) $(PROG) $(PROG2)
-
-
-mmstatd.o:
-       $(CCOBJ) mmstatd.c
-
-mmstat.o:
-       $(CCOBJ) mmstat.c
diff --git a/mmsoftware/mmstatd/src/makepart.sh b/mmsoftware/mmstatd/src/makepart.sh
deleted file mode 100755 (executable)
index 4e19f81..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-# $Id: makepart.sh,v 1.1 2002/12/11 10:16:28 mmondor Exp $
-
-. ../../mmlib/makedefs.sh
-
-OBJS='mmstatd.o mmstat.o'
-BIN1='mmstatd'
-BIN2='mmstat'
-
-if [ "$1" = "clean" ]; then
-       show $RM $OBJS $BIN1 $BIN2
-       exit 0
-fi
-
-INCDIR="-I../../mmlib $STDINC"
-LIBDIR="$STDLIB"
-LIBS='../../mmlib/libmmondor.a -lc'
-
-for obj in $OBJS; do
-       if [ ! -f $obj ]; then
-               src=`$ECHO $obj | $SED 's/\.o$/.c/'`
-               show $CC $CFLAGS -c $INCDIR $src
-       fi
-done
-
-show $CC $CFLAGS -o $BIN1 $INCDIR $LIBDIR $BIN1.o $LIBS
-show $CC $CFLAGS -o $BIN2 $INCDIR $LIBDIR $BIN2.o $LIBS
diff --git a/mmsoftware/mmstatd/src/mmstat.8 b/mmsoftware/mmstatd/src/mmstat.8
deleted file mode 100644 (file)
index 57a69b3..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-.\" $Id: mmstat.8,v 1.8 2004/05/05 23:59:58 mmondor Exp $
-.\"
-.\" Copyright (C) 2002-2004, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd 1 Jan, 2003
-.Dt MMSTAT 8
-.Os
-.Sh NAME
-.Nm mmstat
-.Nd Administration utility to access mmstatd functions
-.Sh SYNOPSIS
-.Nm mmstat [h]report
-.Op Ar key|pattern
-.Nm mmstat reset
-.Ar p|v[a] key|pattern%value
-.Op Ar key|pattern%value ...
-.Nm mmstat update
-.Ar p|v[a] key|pattern%value
-.Op Ar key|pattern%value ...
-.Nm mmstat delete
-.Ar key|pattern
-.Op Ar key|pattern ...
-.Nm mmstat rotate
-.Ar pattern prefix
-.Sh DESCRIPTION
-The
-.Nm mmstatd
-daemon is controled by parameters found in
-.Nm /usr/local/etc/mmstatd.conf
-file. However, a binary is also provided with it to ease administration,
-.Nm mmstat ,
-which still uses the same configuration file. It basically internally uses
-.Xr mmstat 3
-function calls to provide a shell interface to administrators.
-.Nm mmstat
-returns 0 on success, or -1 on error.
-.Pp
-.Nm mmstat [h]report
-.Op Ar key|pattern
-.Pp
-This invokation method permits to retreive a full statistics report, if no
-arguments are specified, a report on a single key, if an absolute key name
-is specified, or (slower) a report on all keys matching specified pattern,
-which can use '*' and '?' wildcards. If
-.Nm hreport
-is specified instead of
-.Nm report ,
-a more humanly readable report form will be shown (can be useful to use
-as-is for CGIs, etc).
-.Pp
-.Nm mmstat reset
-.Ar p|v[a] key|pattern%value
-.Op Ar key|pattern%value ...
-.Pp
-.Nm mmstat update
-.Ar p|v[a] key|pattern%value
-.Op Ar key|pattern%value ...
-.Pp
-Allow to reset or update volatile or persistent keys (either by absolute name
-or pattern matching using '?' and '*'), using specified values. Key/value
-pairs are specified separated with '%' character which is illegal in a key
-name and thus consists of an ideal separator. If an operation is performed on
-a non-existing key, it is automatically created on-the-fly (unless a pattern
-rather than absolute key name). If more than a single
-.Ar key|pattern%value
-pairs are specified, operations are performed atomically within a protected
-transaction on all of them. Of course the number of supplied pairs should not
-exceed
-.Ar MAX_TRANSACT
-as specified in
-.Aq Pa mmstat.h
-headerfile.
-.Ar p
-means that operations should be persistent (as well as any new created key),
-while
-.Ar v
-means that those should be volatile, and thus forgot about in case of a crash
-or
-.Nm mmstatd
-daemon restart. If
-.Ar a
-is also specified, this instructs mmstatd to automatically flush/delete any
-key that reaches 0 after the operation, atomically.
-For reset operations, the value part of a pair specifies what
-value to initialize the corresponding key to; For update operations the current
-key contents is increased by the specified value (which may also be a negative
-number).
-.Pp
-.Nm mmstat delete
-.Ar key|pattern
-.Op Ar key|pattern ...
-.Pp
-Causes specified key(s), represented by their absolute name, or ones matching
-supplied '?' and '*' wildcard matching pattern, to be deleted
-from the statistics database. If more than a single key is specified, a
-transaction-protected atomic operation is performed on all of them, of course
-still subject to
-.Ar MAX_TRANSACT
-according to the maximum number of keys that can be specified.
-.Pp
-.Nm mmstat rotate
-.Ar pattern prefix
-.Pp
-Will perform an atomic rename operation on all persistent keys matching
-specified
-.Ar pattern
-by inserting the specified
-.Ar prefix
-before each matching key name. '*' and '?' wildcards are allowed in the
-.Ar pattern
-argument. This is most useful to perform automatic weekly or monthly rotation
-of statistical keys via a cron events scheduler for instance. This function
-also causes an immediate database sync to disk.
-.Sh EXAMPLES
-Obtain a nicely formatted key/value based statistical report:
-.Bd -literal -offset indent -compact
-mmstat report | awk '{printf "%-64s %d\\n", $6, $5}' | sort
-.Ed
-.Pp
-An alias to obtain a more sophisticated report:
-.Bd -literal -offset indent -compact
-alias report='printf "%10s %-13s %s\\n" "COUNTER" "MODIFIED" "KEY"; mmstat report | awk "{printf \\"date -r %d +%s\\\\\\ %s\\\\\\ %%y%%m%%d.%%H%%M%%S\\n\\", \\$4, \\$6, \\$5}" | sh | sort | awk "{printf \\"%10s %s %s\\n\\", \\$2, \\$3, \\$1}"'
-.Ed
-.Pp
-Show who is currently connected on mmftpd:
-.Bd -literal -offset indent -compact
-mmstat hreport 'mmftpd|who|*'
-.Ed
-.Pp
-Reset all keys with mmftpd in their name to 0:
-.Bd -literal -offset indent -compact
-mmstat reset p '*mmftpd*'
-    or
-mmstat report | grep mmftpd | awk '{printf "%s%%%d ", $6, 0}' |
-       xargs mmstat reset p
-.Ed
-.Pp
-Increase the persistent my|test key by 4 while atomically decreasing the
-persistent my|test2 key by 2:
-.Bd -literal -offset indent -compact
-mmstat update p 'my|test%4' 'my|test2%-2'
-.Ed
-.Pp
-Delete all keys with mmftpd in their name:
-.Bd -literal -offset indent -compact
-mmstat delete '*mmftpd*'
-    or
-mmstat report | awk '{print $6}' | grep mmftpd | xargs mmstat delete
-.Ed
-.Pp
-Example of a monthly cron entry to rename all mmftpd|* keys to YYYYMM-mmftpd|*
-using the last month label:
-.Bd -literal -compact
-30 5 1 * * mmstat rotate 'mmftpd|*' `date -r $((\`date +%s\`-86400)) +%Y%m-`
-.Ed
-.Pp
-Example of a daily cron entry to rename all mmftpd|* keys to YYYYMMDD-mmftpd|*
-using the last day for the stamp:
-.Bd -literal -compact
-30 5 * * * mmstat rotate 'mmftpd|*' `date -r $((\`date +%s\`-86400)) +%Y%m%d-`
-.Ed
-.Sh ENVIRONMENT
-.Bl -tag -width XXXXXXXXXX
-.It Pa Nm MMSTATCONF
-If set, specifies the absolute location of the configuration file to load
-instead of the default
-.Nm /usr/local/etc/mmstatd.conf .
-.El
-.Sh AUTHOR
-mmstat and related daemon and library were written by Matthew Mondor,
-and are Copyright (c) 2002-2004, Matthew Mondor, All rights reserved.
-It originally was written for the mmftpd and mmmail suite of daemons by the
-same author.
-.Sh FILES
-.Bl -tag -width XXXXXXXXXXXXXXXXXXXX -compact
-.It Pa <mmstat.h>
-Headerfile used both by
-.Nm mmstatd
-daemon and
-.Nm mmstat
-utility, defining related
-.Ar MAX_TRANSACT
-variable.
-.Pp
-.It Pa /usr/local/etc/mmstatd.conf
-Configuration file for both
-.Nm mmstatd
-daemon and
-.Nm mmstat
-utility.
-.El
-.Sh SEE ALSO
-.Xr mmstat 3 ,
-.Xr mmstatd.conf 5 ,
-.Xr mmstatd 8 ,
-.Xr apache-mmstat 8 .
-.Sh BUGS
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/mmstatd/src/mmstat.c b/mmsoftware/mmstatd/src/mmstat.c
deleted file mode 100644 (file)
index bed0e54..0000000
+++ /dev/null
@@ -1,425 +0,0 @@
-/* $Id: mmstat.c,v 1.19 2006/11/01 01:32:40 mmondor Exp $ */
-
-/*
- * Copyright (C) 2002-2004, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-
-/* HEADERS */
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-#include <mmtypes.h>
-#include <mmstat.h>
-#include <mmstring.h>
-#include <mmlist.h>
-#include <mmpool.h>
-
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2002-2004\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmstat.c,v 1.19 2006/11/01 01:32:40 mmondor Exp $");
-
-
-
-
-/* STRUCTURES */
-
-struct entnode {
-    pnode_t node;
-    mmstatent_t ent;
-};
-
-
-
-
-/* PROTOTYPES */
-
-int main(int, char **);
-static void usage(void);
-static int stat_report(int, char **);
-static int stat_hreport(int, char **);
-static int stat_reset(int, char **);
-static int stat_update(int, char **);
-static int stat_delete(int, char **);
-static int stat_rotate(int, char **);
-static int compar_entnode(const void *, const void *);
-
-
-
-
-/* FUNCTIONS */
-
-int
-main(int argc, char **argv)
-{
-    int ret = -1;
-
-    /* For efficiency, put the stdout stream in fully buffered mode, so that
-     * we do not cause a syscall to be required for each line (which is silly)
-     */
-    setvbuf(stdout, NULL, 0, _IOFBF);
-    setvbuf(stderr, NULL, 0, _IOFBF);
-    if (argc >= 2) {
-       if (!mm_strcasecmp(argv[1], "report"))
-           ret = stat_report(argc, argv);
-       else if (!mm_strcasecmp(argv[1], "hreport"))
-           ret = stat_hreport(argc, argv);
-       else if (!mm_strcasecmp(argv[1], "reset"))
-           ret = stat_reset(argc, argv);
-       else if (!mm_strcasecmp(argv[1], "update"))
-           ret = stat_update(argc, argv);
-       else if (!mm_strcasecmp(argv[1], "delete"))
-           ret = stat_delete(argc, argv);
-       else if (!mm_strcasecmp(argv[1], "rotate"))
-           ret = stat_rotate(argc, argv);
-       else usage();
-    } else usage();
-
-    /* Make sure that buffers are flushed and return */
-    fflush(stdout);
-    fflush(stderr);
-    return (ret);
-}
-
-
-static
-void usage(void)
-{
-    fprintf(stderr, "\nUsage:\n");
-    fprintf(stderr, "mmstat [h]report [<key|pattern>]\n");
-    fprintf(stderr,
-           "mmstat reset <p|v[a]> <key|pattern>%%<value> \
-[<key|pattern>%%<value> ...]\n");
-    fprintf(stderr,
-           "mmstat update <p|v[a]> <key|pattern>%%<value> \
-[<key|pattern>%%<value> ...]\n");
-    fprintf(stderr, "mmstat delete <key|pattern> [<key|pattern> ...]\n");
-    fprintf(stderr, "mmstat rotate <pattern> <prefix>\n\n");
-}
-
-
-static
-int stat_report(int argc, char **argv)
-{
-    list_t list;
-    pool_t pool;
-    struct entnode *entnod;
-    mmstatres_t *res;
-    mmstatent_t *ent;
-    int ret = 0;
-    char key[KEY_SIZE];
-
-    if (argc == 2 || argc == 3) {
-       mm_memclr(key, KEY_SIZE);
-       if (argc == 3) mm_strncpy(key, argv[2], KEY_SIZE - 1);
-
-       if (pool_init(&pool, "results_pool", malloc, free, NULL, NULL,
-                   sizeof(struct entnode), 32768 / sizeof(struct entnode),
-                   1, 0)) {
-           DLIST_INIT(&list);
-           if ((res = mmstat_report(key))) {
-               /* Cache all results as fast as possible to free the librarian.
-                * Note that we also pre-buffered a 32768 bytes of nodes too,
-                * but which can grow if needed.
-                */
-               while ((ent = mmstat_nextres(res))) {
-                   if ((entnod = (struct entnode *)pool_alloc(&pool,
-                                   FALSE))) {
-                       mm_memcpy(&entnod->ent, ent, sizeof(mmstatent_t));
-                       DLIST_APPEND(&list, (node_t *)entnod);
-                   } else
-                       break;
-               }
-               mmstat_freeres(res);
-               /* Now output list of results to stdout, which could be piped
-                * and processed at an arbitrary rate without hogging the
-                * librarian.
-                */
-               DLIST_FOREACH(&list, entnod) {
-                   ent = &entnod->ent;
-                   printf("%c %d %ld %ld %lld %s\n",
-                          ent->persistent ? 'p' : 'v', ent->uid,
-                          (long)ent->created, (long)ent->modified,
-                          ent->value, ent->key);
-               }
-           } else {
-               printf("Error connecting to mmstatd\n");
-               ret = -1;
-           }
-           pool_destroy(&pool);
-           DLIST_INIT(&list);
-       } else {
-           printf("Error allocating memory for results\n");
-           ret = -1;
-       }
-    } else {
-       usage();
-       ret = -1;
-    }
-
-    return (ret);
-}
-
-
-static
-int stat_hreport(int argc, char **argv)
-{
-    pool_t pool;
-    list_t list;
-    struct entnode *entnod;
-    mmstatres_t *res;
-    mmstatent_t *ent;
-    int ret = 0;
-    char key[KEY_SIZE];
-    bool nomem = FALSE;
-
-    if (argc == 2 || argc == 3) {
-       mm_memclr(key, KEY_SIZE);
-       if (argc == 3) mm_strncpy(key, argv[2], KEY_SIZE - 1);
-
-       if (pool_init(&pool, "results_pool", malloc, free, NULL, NULL,
-                   sizeof(struct entnode), 32768 / sizeof(struct entnode),
-                   1, 0)) {
-           DLIST_INIT(&list);
-           if ((res = mmstat_report(key))) {
-               struct entnode **index;
-               struct tm modifiedt;
-               char modified[15];
-
-               /* Cache all results as fast as possible to free librarian */
-               while ((ent = mmstat_nextres(res))) {
-                   if ((entnod = (struct entnode *)pool_alloc(&pool,
-                                   FALSE))) {
-                       mm_memcpy(&entnod->ent, ent, sizeof(mmstatent_t));
-                       DLIST_APPEND(&list, (node_t *)entnod);
-                   } else
-                       break;
-               }
-               mmstat_freeres(res);
-               /* Now output list of results to stdout, which could be piped
-                * and processed at an arbitrary rate without hogging the
-                * librarian.
-                */
-               /* We want to sort the results by key name; We thus need to
-                * setup an index array.
-                */
-               if ((index = malloc(sizeof(struct entnode *) *
-                               (DLIST_NODES(&list) + 1))) != NULL) {
-                   register int        i = 0;
-                   int64_t             max = 0;
-                   char                fmt[32];
-
-                   DLIST_FOREACH(&list, entnod) {
-                       index[i++] = entnod;
-                       if (entnod->ent.value > max)
-                               max = entnod->ent.value;
-                       else if (-entnod->ent.value > max)
-                               max = -entnod->ent.value;
-                   }
-                   index[i] = NULL;
-
-                   (void) snprintf(fmt, 31, "%lld", max);
-                   i = mm_strlen(fmt) + 1;
-                   (void) snprintf(fmt, 31, "%%%dlld %%s %%s\n", i);
-
-                   qsort(index, DLIST_NODES(&list), sizeof(struct entnode *),
-                           compar_entnode);
-
-                   for (i = 0; index[i] != NULL; i++) {
-                       ent = &(index[i])->ent;
-                       gmtime_r(&ent->modified, &modifiedt);
-                       strftime(modified, 14, "%y%m%d.%H%M%S", &modifiedt);
-                       (void) printf(fmt, ent->value, modified, ent->key);
-                   }
-
-                   free(index);
-               } else
-                   nomem = TRUE;
-           } else {
-               printf("Error connecting to mmstatd\n");
-               ret = -1;
-           }
-           pool_destroy(&pool);
-           DLIST_INIT(&list);
-       } else
-           nomem = TRUE;
-       if (nomem) {
-           printf("Error allocating memory for results\n");
-           ret = -1;
-       }
-    } else {
-       usage();
-       ret = -1;
-    }
-
-    return (ret);
-}
-
-
-static
-int stat_reset(int argc, char **argv)
-{
-    mmstat_t mms;
-    int i, ret = 0;
-    char *arg, *args[3];
-    bool persistent = FALSE, autoflush = FALSE, ok = TRUE;
-
-    if (argc > 3) {
-       if (mm_strchr(argv[2], 'p')) persistent = TRUE;
-       if (mm_strchr(argv[2], 'v')) persistent = FALSE;
-       if (mm_strchr(argv[2], 'a')) autoflush = TRUE;
-       if (mmstat_init(&mms, persistent, autoflush)) {
-           mmstat_transact(&mms, TRUE);
-           for (i = 3; i < argc; i++) {
-               arg = argv[i];
-               if (mm_strspl(args, arg, 2, '%') == 2)
-                   mmstat(&mms, STAT_RESET, atol(args[1]), "%s", args[0]);
-           }
-           if (!mmstat_transact(&mms, FALSE)) {
-               printf("Error sending request to mmstatd\n");
-               ret = -1;
-           }
-       } else {
-           printf("Error opening mmstatd handler\n");
-           ret = -1;
-       }
-    } else
-       ok = FALSE;
-    if (!ok) {
-       usage();
-       ret = -1;
-    }
-
-    return (ret);
-}
-
-
-static int
-stat_update(int argc, char **argv)
-{
-    mmstat_t mms;
-    int i, ret = 0;
-    char *arg, *args[3];
-    bool persistent = FALSE, autoflush = FALSE, ok = TRUE;
-
-    if (argc > 3) {
-       if (mm_strchr(argv[2], 'p')) persistent = TRUE;
-       if (mm_strchr(argv[2], 'v')) persistent = FALSE;
-       if (mm_strchr(argv[2], 'a')) autoflush = TRUE;
-       if (mmstat_init(&mms, persistent, autoflush)) {
-           mmstat_transact(&mms, TRUE);
-           for (i = 3; i < argc; i++) {
-               arg = argv[i];
-               if (mm_strspl(args, arg, 2, '%') == 2)
-                   mmstat(&mms, STAT_UPDATE, atol(args[1]), "%s", args[0]);
-           }
-           if (!mmstat_transact(&mms, FALSE)) {
-               printf("Error sending request to mmstatd\n");
-               ret = -1;
-           }
-       } else {
-           printf("Error opening mmstatd handler\n");
-           ret = -1;
-       }
-    } else
-       ok = FALSE;
-    if (!ok) {
-       usage();
-       ret = -1;
-    }
-
-    return (ret);
-}
-
-
-static int
-stat_delete(int argc, char **argv)
-{
-    mmstat_t mms;
-    int i, ret = 0;
-
-    if (argc > 2) {
-       if (mmstat_init(&mms, TRUE, TRUE)) {
-           mmstat_transact(&mms, TRUE);
-           for (i = 2; i < argc; i++)
-               mmstat(&mms, STAT_DELETE, 0, "%s", argv[i]);
-           if (!mmstat_transact(&mms, FALSE)) {
-               printf("Error sending request to mmstatd\n");
-               ret = -1;
-           }
-       } else {
-           printf("Error opening mmstatd handler\n");
-           ret = -1;
-       }
-       exit(0);
-    } else {
-       usage();
-       ret = -1;
-    }
-
-    return (ret);
-}
-
-
-static int
-stat_rotate(int argc, char **argv)
-{
-    int ret = 0;
-
-    if (argc == 4) {
-       if (!mmstat_rotate(argv[2], argv[3])) {
-           printf("Error sending request to mmstatd\n");
-           ret = -1;
-       }
-    } else {
-       usage();
-       ret = -1;
-    }
-
-    return (ret);
-}
-
-
-static int
-compar_entnode(const void *from, const void *to)
-{
-    const struct entnode **f = (const struct entnode **)from,
-       **t = (const struct entnode **)to;
-
-    return (mm_strcmp((*f)->ent.key, (*t)->ent.key));
-}
diff --git a/mmsoftware/mmstatd/src/mmstatd.8 b/mmsoftware/mmstatd/src/mmstatd.8
deleted file mode 100644 (file)
index df84f2a..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-.\" $Id: mmstatd.8,v 1.8 2004/10/18 17:34:15 mmondor Exp $
-.\"
-.\" Copyright (C) 2002-2004, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd 11 Dec, 2002
-.Dt MMSTATD 8
-.Os
-.Sh NAME
-.Nm mmstatd
-.Nd
-Statistics librarian and logger daemon with recovery and transaction support
-.Sh SYNOPSIS
-.Nm mmstatd Op Ar config_file
-.Sh DESCRIPTION
-.Nm mmstatd
-consists of a statistics librarian daemon used by the familly of
-mm utilities (mmmail, mmftpd, etc). It simply allows applications to record
-statistical information using a key-based system. It also supports transactions
-and crash recovery logging. Moreover, it features volatile and consistant
-database entries, with creation and modification timestamps.
-.Pp
-The main reason why I wrote it was because syslog does not consist of an
-ideal approach to count statistics, and that using an SQL server for this
-is overkill, especially with required SQL commands parsing and atomic-safe
-transaction locks. db4 could have been more efficient, but it is quite easy
-to rival with it according to size. The size of mmstatd and mmstat library is
-very small, and it's performance is decent. Moreover a database server would
-consider all keys as persistent storage, when a requirement for both
-persistent and volatile ones was met.
-.Pp
-.Nm The way it works
-.Pp
-Basically, it starts up two asynchroneous processes, the librarian and logger.
-.Pp
-The librarian is responsible for managing the database and affecting changes
-while asynchroneously reading available logs. It also permits obtention of
-statistics report connecting to a Unix domain stream socket. The librarian
-synchronizes the memory database to disk every once in a while, recording
-the current position in the logs, and deleting obsolete, already synchronized
-logs when required. This synchronization to disk is only performed at large
-time intervals, to minimize CPU and drive load, and maximise responsiveness.
-The librarian also establishes a listening UNIX stream socket, to serve
-reports and rotation requests.
-.Pp
-The logger, in turn, listens to a Unix datagram socket, and writes the logs,
-syncing them to disk frequently enough, for both the librarian and logger.
-This allows the logs to be used for recovery of persistent modifications that
-were performed since the last full database sync. Moreover, it permits the
-clients to always be able to send more packets without being subject to the
-librarian processing, avoiding a bottleneck.
-.Pp
-Every time mmstatd is started, it first ensures to run with normal user
-privileges, then looks for recovery logs and performs necessary modifications
-to the database, before forcing a sync of the new database to disk, deleting
-all recovery logs. It then launches the two asynchroneous processes which then
-become ready to serve their tasks.
-.Pp
-Using this design allows applications to use a simple syslog-like API to
-update statistics, in a very fast manner. For the various mm daemons, it
-serves as a who database, using volatile storage, and as various statistical
-tasks using persistent storage.
-.Pp
-The logging socket, used to send update requests, as well as the status socket,
-are independent and can have specific permissions, so that only applications
-who should access the service may. The user application interface library is
-quite simple to use by programs wanting to keep their statistics using mmstatd.
-See the
-.Xr mmstat 3
-man page for more information.
-.Pp
-The internal format used to store the database, as well as the recovery
-logging, are now endian-independent, as well as native integer size
-independent. This means that those files should easily be migrated to another
-operating system and/or hardware architecture without modifications.
-The file formats are saved in network byte order (big endian) and the internal
-memory representation is in local host order corresponding to the particular
-architecture.
-.Pp
-.Sh INSTALLATION
-.Nm mmstatd
-is installed by the make.sh scripts of both
-.Nm mmftpd
-and
-.Nm mmmail
-by Matthew Mondor. It's administration is made through
-.Nm /usr/local/etc/mmstatd.conf
-(See
-.Xr mmstatd.conf 5
-man page) and
-.Nm mmstat
-(See
-.Xr mmstat 8
-man page).
-.Pp
-Here is an overview of standard permissions various files should have:
-.Pp
-.Bd -literal -offset indent -compact
-Permissions Owner    Group   File
-
--rwxr-x---  root     staff   /usr/local/sbin/mmstat
--rwx------  root     wheel   /usr/local/sbin/mmstatd
-
-drwxr-x---  mmstatd  mmstat  /var/mmstatd
-
-s-w--w----  mmstatd  mmstat  /var/mmstatd/mmstatd_log.sock
-srw-rw----  mmstatd  staff   /var/mmstatd/mmstatd_stat.sock
-.Ed
-.Pp
-Basically, the administrator will need access to
-.Nm mmstat
-binary as well as to both
-.Nm /var/mmstatd/*.sock
-files. Applications using the
-.Xr mmstat 3
-facility require access to the
-.Nm /var/mmstatd/mmstatd_log.sock
-file only. Only uid zero should have access to
-.Nm /var/mmstatd
-directory and
-.Nm mmstatd
-daemon.
-.Pp
-.Nm mmstatd
-should normally be started before any other daemons using the
-.Xr mmstat 3
-interface. Although this is not obligatory, it is highly
-recommended. As it will take the time to perform recovery before calling
-.Xr fork 2
-other daemons will have a clean and ready daemon to serve their requests,
-so a startup script typically would use something like:
-.Pp
-.Bd -literal -offset indent -compact
-/usr/local/sbin/mmstatd
-/usr/local/sbin/mmftpd
-/usr/local/sbin/mmsmtpd
-/usr/local/sbin/mmpop3d
-.Ed
-.Sh FILES
-.Bl -tag -width XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -compact
-.It Pa /usr/local/etc/mmstatd.conf
-This file consists of the configuration file for
-.Nm mmstatd
-and controls all it's configurable parameters.
-.Pp
-.It Pa /var/mmstatd
-The mmstat environment directory, where recovery logs and database file are
-located. The default configuration also stores UNIX domain sockets there.
-.Pp
-.It Pa /var/mmstatd/mmstatd_stat.sock
-The UNIX stream socket on which listens
-.Nm mmstatd
-librarian process, used by the administrator via
-.Nm mmstat
-binary to query statistical reports and request key rotations.
-.Pp
-.It Pa /var/mmstatd/mmstatd_log.sock
-The UNIX datagram socket on which listens
-.Nm mmstatd
-logger process, used by all applications using the
-.Xr mmstat 3
-interface to update statistics.
-.Pp
-.It Pa /var/mmstatd/mmstatd.db
-The database file used to permanently store persistent storage statistical
-keys. When a disk synchronization occurs, a temporary file is used to save
-the database on the same filesystem, and
-.Xr rename 2
-is used to move it over this file in an atomic manner.
-.Pp
-.It Pa /var/mmstatd/????????.log
-Log files internally used and automatically maintained by
-.Nm mmstatd
-for crash recovery.
-.Pp
-.It Pa /usr/local/sbin/mmstatd
-The actual daemon binary documented by
-.Xr mmstatd 8
-.Pp
-.It Pa /usr/local/sbin/mmstat
-The administration utility documented by
-.Xr mmstat 8
-.El
-.Sh ENVIRONMENT
-.Bl -tag -width XXXXXXXXXX
-.It Pa Nm MMSTATCONF
-If set, specifies the absolute location of the configuration file to load
-instead of the default
-.Nm /usr/local/etc/mmstatd.conf .
-If a configuration file name is specified on the command line, it will
-override this environment variable even if it was set.
-.El
-.Sh AUTHOR
-The suite of mmstat daemon, related utilities and documentation were written
-by Matthew Mondor, and are
-Copyright (c) 2002-2004, Matthew Mondor, All rights reserved.
-They were developped
-under NetBSD 1.5.3 for the mmftpd and mmmail suite of daemons from the same
-author.
-.Sh SEE ALSO
-.Xr mmstat 3 ,
-.Xr mmstatd.conf 5 ,
-.Xr mmstat 8 ,
-.Xr apache-mmstat 8 ,
-.Xr rename 2 ,
-.Xr fork 2 ,
-.Xr unix 4 .
-.Sh BUGS
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/mmstatd/src/mmstatd.c b/mmsoftware/mmstatd/src/mmstatd.c
deleted file mode 100644 (file)
index d98a07d..0000000
+++ /dev/null
@@ -1,1991 +0,0 @@
-/* $Id: mmstatd.c,v 1.39 2004/06/09 21:12:45 mmondor Exp $ */
-
-/*
- * Copyright (C) 2002-2004, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* TODO:
- * - Finish client packet uid credential checking, credentials have to be
- *   passed through the unix domain socket
- */
-
-
-
-
-/* HEADERS */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/uio.h>
-#include <sys/file.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include <poll.h>
-#include <syslog.h>
-#include <signal.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <dirent.h>
-#include <pwd.h>
-#include <grp.h>
-#include <errno.h>
-
-#include <mmtypes.h>
-#include <mmpool.h>
-#include <mmhash.h>
-#include <mmstring.h>
-#include <mmstat.h>
-#include <mmstatd.h>
-#include <mmreadcfg.h>
-#include <mmlog.h>
-#include <mmlimitrate.h>
-
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2002-2004\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmstatd.c,v 1.39 2004/06/09 21:12:45 mmondor Exp $");
-
-
-
-
-/* GLOBALS */
-
-static struct mmstat_config CONF;
-static pid_t librarian_pid = -1, logger_pid = -1;
-static pool_t key_pool;
-static hashtable_t key_table;
-static int pipefds[2], syncbytes = 0;
-static bool pipesend = TRUE;
-
-
-
-
-/* FUNCTIONS */
-
-static pid_t
-process_spawn(int (*function)(void *), void *params, bool leader)
-{
-    pid_t pid = -1;
-    int fd;
-
-    /* Create new process */
-    if (!(pid = fork())) {
-       struct sigaction act;
-
-       /* Child */
-       if (leader) setsid();
-       chdir("/");
-       umask(0);
-
-       /* Make sure that stdin, stdout and stderr are safe */
-       if ((fd = open("/dev/null", O_RDWR)) != -1) {
-           dup2(fd, 0);
-           dup2(fd, 1);
-           dup2(fd, 2);
-           if (fd > 2)
-               close(fd);
-       }
-
-       /* Setup our break handler */
-       act.sa_handler = sighandler;
-       act.sa_flags = SA_NOCLDWAIT;
-       sigemptyset(&act.sa_mask);
-       sigaction(SIGTERM, &act, NULL);
-       sigaction(SIGSEGV, &act, NULL);
-       sigaction(SIGPIPE, &act, NULL);
-
-       /* Signals we want to ignore */
-       signal(SIGTTOU, SIG_IGN);
-       signal(SIGTTIN, SIG_IGN);
-       signal(SIGTSTP, SIG_IGN);
-
-       /* Simply call the wanted child function */
-       exit(function(params));
-
-    }
-
-    /* Parent */
-    return (pid);
-}
-
-
-static void
-sighandler(int sig)
-{
-    switch (sig) {
-    case SIGTERM:
-       syslog(LOG_NOTICE, "Received SIGTERM, cleaning up");
-       signal(SIGTERM, SIG_IGN);
-       kill(0, SIGTERM);
-       exit(0);
-       break;
-    case SIGSEGV:
-       syslog(LOG_NOTICE, "Received SIGSEGV! Cleaning up");
-       kill(0, SIGTERM);
-       exit(0);
-       break;
-    case SIGPIPE:
-       pipesend = FALSE;
-       break;
-    default:
-       syslog(LOG_NOTICE, "Signal handler catched unexpected signal");
-       break;
-    }
-}
-
-
-/* This uses an fd which remains open in child processes, if they close it the
- * lock seems to be released automatically.
- */
-static bool
-lock_check(const char *file)
-{
-    int fd;
-
-    if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600)) != -1) {
-       if (!(flock(fd, LOCK_EX | LOCK_NB)))
-           return (TRUE);
-       close(fd);
-    }
-
-    return (FALSE);
-}
-
-
-static int
-unix_init(const char *name, gid_t group, mode_t mode, int backlog, bool stream,
-       bool del)
-{
-    int sock;
-    struct sockaddr_un sau;
-
-    if (del) unlink(name);
-
-    /* Open public UNIX domain socket */
-    if (stream) {
-       if ((sock = socket(AF_LOCAL, SOCK_STREAM, 0)) != -1) {
-           mm_strncpy(sau.sun_path, name, 100);
-           sau.sun_family = AF_UNIX;
-           if (bind(sock, (struct sockaddr *)&sau, sizeof(struct sockaddr_un))
-                   != -1) {
-               if (!chmod(name, mode)) {
-                   chown(name, -1, group);
-                   if (!(listen(sock, backlog)))
-                       return (sock);
-                   else
-                       DEBUG_PRINTF("unix_init", "listen(%d)", sock);
-               } else
-                   DEBUG_PRINTF("unix_init", "chmod(%s, %d)", name, mode);
-           } else
-               DEBUG_PRINTF("unix_init", "bind(%d)", sock);
-           close(sock);
-       } else
-           DEBUG_PRINTF("unix_init", "socket()");
-    } else {
-       if ((sock = socket(AF_LOCAL, SOCK_DGRAM, 0)) != -1) {
-           int opt;
-
-           /* Set output buffer size */
-           opt = (int)BALIGN_CEIL(sizeof(struct log_entry) * MAX_TRANSACT,
-                   1024);
-           if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(int))
-                   == -1)
-               DEBUG_PRINTF("unix_init", "setsockopt(%d, SO_RCVBUF)", sock);
-
-           mm_strncpy(sau.sun_path, name, 100);
-           sau.sun_family = AF_UNIX;
-           if (bind(sock, (struct sockaddr *)&sau, sizeof(struct sockaddr_un))
-                   != -1) {
-               if (!chmod(name, mode)) {
-                   chown(name, -1, group);
-                   return (sock);
-               } else
-                   DEBUG_PRINTF("unix_init", "chmod(%s, %d)", name, mode);
-           } else
-               DEBUG_PRINTF("unix_init", "bind(%d)", sock);
-           close(sock);
-       } else
-           DEBUG_PRINTF("unix_init", "socket()");
-    }
-
-    return (-1);
-}
-
-
-static bool
-log_match(const char *str, const char *pat)
-{           
-    for (; *pat != '*'; pat++, str++) {
-       if (*str == '\0') {
-           if (*pat != '\0')
-               return FALSE;
-           else
-               return TRUE;
-       }
-       if(*str != *pat && *pat != '?')
-           return FALSE;
-    }
-    while (pat[1] == '*')
-       pat++;
-    do
-       if (log_match(str, pat + 1))
-           return TRUE;
-    while (*str++ != '\0') ;
-
-    return FALSE;
-}
-
-
-/* Writes requested log entries to specified fd, and if required automatically
- * perform logfile rotation, of course putting a mark at the end of the logfile
- * pointing to the next one continueing it. Files are rotated when reaching
- * approximately one megabyte in length. Returns TRUE on success or FALSE on
- * fatal error (eg: disk full).
- *
- * Note that the logentry we are writing is always in network byte order here.
- * We however receive host byte order entries, but are converting them as
- * appropriate, as well as generate network order entries when a new file
- * entry is required because of rotation.
- */
-static bool
-logentries_write(int pfd, struct log_entry *entries, int len, int *fd,
-       u_int32_t *lognum, off_t *logpos)
-{
-    ssize_t l;
-    bool ok;
-    char filename[256], dat[MAX_TRANSACT];
-
-    ok = TRUE;
-    l = len * sizeof(struct log_entry);
-
-    /* First perform logfile rotation if required */
-    if (*logpos + l > CONF.max_logsize) {
-       struct log_entry newentry;
-       int newfd;
-
-       if ((*lognum)++ > 99999999)
-           *lognum = 0;
-       *logpos = 0;
-       snprintf(filename, 255, "%s/%08u.log", CONF.ENV_DIR, *lognum);
-       if ((newfd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600))
-               != -1) {
-           fsync(newfd);
-           mm_memclr(&newentry, sizeof(struct log_entry));
-           newentry.type = (int32_t)BYTEORDER_NETWORK32(
-                   (u_int32_t)STAT_NEWFILE);
-           newentry.un.newfile.lognum = BYTEORDER_NETWORK32(*lognum);
-           if ((write(*fd, &newentry, sizeof(struct log_entry))) !=
-                   sizeof(struct log_entry))
-               DEBUG_PRINTF("logentries_write", "write(STAT_NEWFILE)");
-           (void) fsync(*fd);
-           (void) close(*fd);
-           *fd = newfd;
-           (void) write(pfd, dat, 1);
-       } else {
-           DEBUG_PRINTF("logentries_write", "open(%s)", filename);
-           ok = FALSE;
-       }
-    }
-
-    /* Write our new log entry */
-    if (ok) {
-       time_t tim;
-       int i, type;
-
-       tim = time(NULL);
-       for (i = 0; i < len; i++) {
-           /* Mark entry time, in network byte order */
-           entries[i].time = BYTEORDER_NETWORK32((u_int32_t)tim);
-
-           /* Convert entry to network byte order */
-           type = (int)entries[i].type;
-           entries[i].type = (int32_t)BYTEORDER_NETWORK32((u_int32_t)type);
-           entries[i].uid = BYTEORDER_NETWORK32(entries[i].uid);
-           entries[i].persistent = BYTEORDER_NETWORK16(
-                   entries[i].persistent);
-           entries[i].autoflush = BYTEORDER_NETWORK16(entries[i].autoflush);
-           if (type == STAT_TRANSACT)
-               entries[i].un.transact.begin = BYTEORDER_NETWORK32(
-                       entries[i].un.transact.begin);
-           else if (type == STAT_UPDATE)
-               entries[i].un.update.modifier = (int64_t)BYTEORDER_NETWORK64(
-                       (u_int64_t)entries[i].un.update.modifier);
-           else if (type == STAT_RESET)
-               entries[i].un.reset.value = (int64_t)BYTEORDER_NETWORK64(
-                       (u_int64_t)entries[i].un.reset.value);
-       }
-
-       /* Write to logfile */
-       if (write(*fd, entries, l) == l) {
-           *logpos += l;
-           /* A trick to keep resonable physical disk sync rate */
-           syncbytes += l;
-           if (syncbytes >= CONF.SYNC_BYTES) {
-               syncbytes = 0;
-               (void) fdatasync(*fd);
-           }
-           (void) write(pfd, dat, len);
-       } else {
-           DEBUG_PRINTF("logentries_write", "write(STAT_*)");
-           ok = FALSE;
-       }
-    }
-
-    return (ok);
-}
-
-
-/* This function attempts to read a log entry from specified fd, transparently
- * rotating to the new logfile when required, and updates fd and lognum via
- * provided pointers. If pfd is -1, we attempt to read an entry, and return
- * FALSE if none could be read. Otherwise we attempt to read for an entry
- * monitoring pfd for new data notification, until at least a full entry
- * could be read. We return TRUE if an entry could be read.
- *
- * Note that the entries we are reading are in network byte order, which means
- * that we must convert them to host byte order after reading.
- */
-static bool
-logentry_read(int pfd, struct log_entry *entry, int *fd, u_int32_t *lognum,
-       off_t *logpos)
-{
-    char filename[256], c;
-    int newfd;
-    bool ok, redo;
-    struct pollfd fds[] = {
-       {pfd, POLLIN, 0}
-    };
-
-    redo = TRUE;
-    while (redo) {
-       redo = FALSE;
-
-       ok = FALSE;
-       if (pfd == -1) {
-           if ((read(*fd, entry, sizeof(struct log_entry))) ==
-                   sizeof(struct log_entry))
-               ok = TRUE;
-       } else {
-           for (;;) {
-               if ((poll(fds, 1, 5000)) > 0) {
-                   if (fds[0].revents & POLLIN) {
-                       if ((read(pfd, &c, 1)) == 1) {
-                           if ((read(*fd, entry, sizeof(struct log_entry)))
-                                   == sizeof(struct log_entry))
-                               ok = TRUE;
-                           else
-                               DEBUG_PRINTF("logentry_read",
-                                       "read(%d, %d) partial read",
-                                       *fd, (int)sizeof(struct log_entry));
-                           break;
-                       }
-                   }
-               }
-           }
-       }
-
-       if (ok) {
-           /* Convert type to host byte order */
-           entry->type = (int32_t)BYTEORDER_HOST32((u_int32_t)entry->type);
-           /* logentry_debug('|', entry); */
-           *logpos += sizeof(struct log_entry);
-           /* If required switch to next logfile */
-           if (entry->type == (int32_t)STAT_NEWFILE) {
-               /* Convert new file number to host byte order */
-               entry->un.newfile.lognum = BYTEORDER_HOST32(
-                       entry->un.newfile.lognum);
-               snprintf(filename, 255, "%s/%08u.log", CONF.ENV_DIR,
-                       entry->un.newfile.lognum);
-               if ((newfd = open(filename, O_RDONLY)) != -1) {
-                   close(*fd);
-                   *fd = newfd;
-                   *logpos = 0;
-                   *lognum = entry->un.newfile.lognum;
-                   redo = TRUE;
-               } else {
-                   DEBUG_PRINTF("logentry_read", "open(%s)", filename);
-                   ok = FALSE;
-               }
-           }
-       }
-
-    }
-
-    return (ok);
-}
-
-
-/* This function attempts to read at least one entry, but all entries of a
- * transaction if any is detected. If pfd is -1, we return FALSE if we
- * cannot read an entry or the whole transaction, otherwise we wait for
- * more data to be available using fdb with poll(). We only return TRUE
- * if a single entry or whole transaction could be read.
- * If STAT_NEWFILE entry is encoutered, auto rotation to the new logfile
- * is performed and fd,lognum,logpos are updated via the provided pointers,
- * transparently.
- * The STAT_TRANSACT header and footer entries are never put in the buffer,
- * this way their persistent flag is ignored.
- * IMPORTANT: Because of the way this function works to prevent additionnal
- * memory copy operations, the supplied buffer size should at least have one
- * additionnal entry than specified maximum size.
- */
-static int
-logentries_read(int pfd, struct log_entry *entries, int max, int *fd,
-       u_int32_t *lognum, off_t *logpos)
-{
-    struct log_entry *ptr;
-    int len;
-    bool transact;
-
-    transact = FALSE;
-    ptr = entries;
-    len = 0;
-
-    if (logentry_read(pfd, entries, fd, lognum, logpos)) {
-       /* Type already converted to host byte order */
-       if (entries->type == STAT_TRANSACT) {
-           entries->un.transact.begin = BYTEORDER_HOST32(
-                   entries->un.transact.begin);
-           if (entries->un.transact.begin)
-               transact = TRUE;
-           else {
-               /* Mismatch */
-               len = 0;
-               DEBUG_PRINTF("logentries_read",
-                       "Mismatched transaction start");
-           }
-       } else
-           len++;
-    }
-
-    /* If we fill the buffer of max entries or if we reach EOF before end of
-     * transaction marker can be found, we simply drop the whole transaction
-     * and return 0. That is where we need a read-ahead buffer, and require
-     * an additionnal entry.
-     */
-    while (transact) {
-       if (len > max) {
-           len = 0;
-           syslog(LOG_NOTICE, "logentries_read() - MAX_TRANSACT exceeded");
-           break;
-       }
-       if (!logentry_read(pfd, ptr, fd, lognum, logpos)) {
-           len = 1;
-           break;
-       } else {
-           /* Type already in host byte order */
-           if (ptr->type == STAT_TRANSACT) {
-               ptr->un.transact.begin = BYTEORDER_HOST32(
-                       ptr->un.transact.begin);
-               if (ptr->un.transact.begin) {
-                   /* Mismatch */
-                   len = 0;
-                   DEBUG_PRINTF("logentries_read",
-                           "Mismatched transaction end");
-               }
-               break;
-           } else {
-               ptr++;
-               len++;
-           }
-       }
-    }
-
-    return (len);
-}
-
-
-/* Apply requested log entry to the live db.
- * STAT_NEWFILE or STAT_TRANSACT entries are never processed through this
- * function.
- */
-static bool
-logentry_process(struct log_entry *entry, bool tmp)
-{
-    enum stat_type type;
-
-    /* logentry_debug(':', entry); */
-
-    /* Type already in host byte order. Convert other first level elements. */
-    type = entry->type;
-    entry->uid = BYTEORDER_HOST32(entry->uid);
-    entry->time = BYTEORDER_HOST32(entry->time);
-    entry->persistent = BYTEORDER_HOST16(entry->persistent);
-    entry->autoflush = BYTEORDER_HOST16(entry->autoflush);
-
-    if (tmp || entry->persistent) {
-       register size_t len;
-       register char *ptr;
-
-       /* Verify if we should perform wildcard matching and perform an atomic
-        * operation on all matching keys
-        */
-       for (ptr = entry->key; *ptr != '\0'; ptr++)
-           if (*ptr == '?' || *ptr == '*')
-               break;
-       len = mm_strlen(entry->key);
-
-       if (*ptr == '\0') {     /* Operation on single key */
-           struct key_node *knod;
-
-           /* Locate corresponding key in table */
-           if ((knod = (struct key_node *)hashtable_lookup(&key_table,
-                           entry->key, len + 1)) != NULL) {
-               /* Key exists, make sure that UID matches entry creator's or
-                * that operator was UID 0
-                */
-               if (knod->entry.uid != entry->uid && entry->uid != 0) {
-                   syslog(LOG_NOTICE, "Unauthorized UID!");
-                   return FALSE;
-               }
-               if (type == STAT_UPDATE)
-                   knod->entry.value += (int64_t)BYTEORDER_HOST64(
-                           (u_int64_t)entry->un.update.modifier);
-               else if(type == STAT_RESET)
-                   knod->entry.value = (int64_t)BYTEORDER_HOST64(
-                           (u_int64_t)entry->un.reset.value);
-               if (type == STAT_DELETE || (knod->entry.value == 0 &&
-                           entry->autoflush)) {
-                   /* Delete entry */
-                   hashtable_unlink(&key_table, (hashnode_t *)knod);
-                   pool_free((pnode_t *)knod);
-               } else
-                   knod->entry.modified = entry->time;
-           } else {
-               /* Key does not exist */
-               if (type == STAT_DELETE)
-                   return TRUE;
-               if (type == STAT_UPDATE || type == STAT_RESET) {
-                   if (type == STAT_UPDATE)
-                       entry->un.update.modifier = (int64_t)BYTEORDER_HOST64(
-                               (u_int64_t)entry->un.update.modifier);
-                   else
-                       entry->un.reset.value = (int64_t)BYTEORDER_HOST64(
-                               (u_int64_t)entry->un.reset.value);
-                   if (!(entry->autoflush &&
-                               (type == STAT_UPDATE ?
-                                       entry->un.update.modifier :
-                                       entry->un.reset.value) == 0)) {
-                       /* Create new entry */
-                       if ((knod = (struct key_node *)pool_alloc(&key_pool,
-                                       FALSE)) != NULL) {
-                           mm_memcpy(knod->entry.key, entry->key, len + 1);
-                           knod->entry.value = (type == STAT_UPDATE ?
-                               entry->un.update.modifier :
-                               entry->un.reset.value);
-                           knod->entry.uid = (uid_t)entry->uid;
-                           knod->entry.created = knod->entry.modified =
-                               (time_t)entry->time;
-                           knod->entry.persistent = (bool)entry->persistent;
-                           knod->processed = FALSE;
-                           hashtable_link(&key_table, (hashnode_t *)knod,
-                                   knod->entry.key, len + 1, FALSE);
-                       } else
-                           return FALSE;
-                   }
-               }
-           }
-
-       } else          /* Operation on all keys matching pattern */
-           hashtable_iterate(&key_table, logentry_process_iterator, entry);
-
-    }
-
-    return TRUE;
-}
-
-
-static bool
-logentry_process_iterator(hashnode_t *hnod, void *udata)
-{
-    struct key_node *knod = (struct key_node *)hnod;
-    struct log_entry *entry = udata;
-
-    /* Most elements have been converted to host byte order already */
-    if ((knod->entry.uid == entry->uid || entry->uid == 0) &&
-           log_match(knod->entry.key, entry->key)) {
-       if (entry->type == STAT_RESET)
-           knod->entry.value = (int64_t)BYTEORDER_HOST64(
-                   (u_int64_t)entry->un.reset.value);
-       else if (entry->type == STAT_UPDATE)
-           knod->entry.value += (int64_t)BYTEORDER_HOST64(
-                   (u_int64_t)entry->un.update.modifier);
-       if (entry->type == STAT_DELETE || (knod->entry.value == 0 &&
-                   entry->autoflush)) {
-           hashtable_unlink(&key_table, (hashnode_t *)knod);
-           pool_free((pnode_t *)knod);
-       } else
-           knod->entry.modified = (time_t)entry->time;
-    }
-
-    return TRUE;
-}
-
-
-static bool
-logentries_process(struct log_entry *entries, int len, bool tmp)
-{
-    int i;
-    bool ok = TRUE;
-
-    for (i = 0; i < len; i++) {
-       if (!logentry_process(&entries[i], tmp)) {
-           ok = FALSE;
-           break;
-       }
-    }
-
-    return (ok);
-}
-
-
-/* Only used for debugging when testing/developing. Might also need endian
- * conversion macros.
- */
-/*
-static void
-logentry_debug(char c, struct log_entry *entry)
-{
-    switch (entry->type) {
-       case STAT_TRANSACT:
-           syslog(LOG_NOTICE, "%c STAT_TRANSACT u=%d p=%d a=%d beg=%d k=%s",
-                   c, entry->uid, entry->persistent, entry->autoflush,
-                   entry->un.transact.begin, entry->key);
-           break;
-       case STAT_NEWFILE:
-           syslog(LOG_NOTICE, "%c STAT_NEWFILE u=%d p=%d a=%d num=%ld k=%s",
-                   c, entry->uid, entry->persistent, entry->autoflush,
-                   entry->un.newfile.lognum, entry->key);
-           break;
-       case STAT_UPDATE:
-           syslog(LOG_NOTICE, "%c STAT_UPDATE u=%d p=%d a=%d mod=%lld k=%s",
-                   c, entry->uid, entry->persistent, entry->autoflush,
-                   entry->un.update.modifier, entry->key);
-           break;
-       case STAT_RESET:
-           syslog(LOG_NOTICE, "%c STAT_RESET u=%d p=%d a=%d val=%lld k=%s",
-                   c, entry->uid, entry->persistent, entry->autoflush,
-                   entry->un.reset.value, entry->key);
-           break;
-       case STAT_DELETE:
-           syslog(LOG_NOTICE, "%c STAT_DELETE u=%d p=%d a=%d k=%s",
-                   c, entry->uid, entry->persistent, entry->autoflush,
-                   entry->key);
-           break;
-       default:
-           syslog(LOG_NOTICE, "%c Unknown entry type!", c);
-    }
-}
-*/
-
-
-/* This function prepares the db lists, and attempts to load previously saved
- * database and sync state. If part of the database cannot be loaded, we
- * log an error via syslog but will either provide an empty or incomplete
- * db in memory.
- */
-static void
-db_load(u_int32_t *lognum, off_t *logpos)
-{
-    char filename[256];
-    FILE *fh;
-    bool ok;
-    u_int32_t version, ver;
-
-    ok = TRUE;
-    *lognum = 0;
-    *logpos = 0;
-
-    snprintf(filename, 255, "%s/mmstatd.db", CONF.ENV_DIR);
-    if (pool_init(&key_pool, "key_pool", malloc, free, NULL, NULL,
-               sizeof(struct key_node), 32768 / sizeof(struct key_node),
-               0, 0)) {
-       if (hashtable_init(&key_table, "key_table", HT_DEFAULT_CAPACITY,
-                   HT_DEFAULT_FACTOR, malloc, free,
-                   mm_memcmp, mm_memhash32, TRUE)) {
-           if ((fh = fopen(filename, "rb")) != NULL) {
-               /* We now remember how to load old mmstatd database files,
-                * since at times the format changes accross versions.
-                * First determine which version, and call the appropriate
-                * function.
-                */
-               if (fread(&ver, sizeof(u_int32_t), 1, fh) == 1) {
-                   char format;
-                   const u_int8_t *p;
-
-                   /* We need to still support old host-order saved formats
-                    * with little endian architectures. This means that we
-                    * need to differenciate little endian saved version tag
-                    * from big endian (network order) one.
-                    * We know that we used a large word, a number substracted
-                    * from 0xffffffff. This means that if it was saved in
-                    * network order, we should have the first of the two
-                    * bytes of the 32-bit word be 0xffff. Otherwise, we know
-                    * that the two last ones should be 0xffff, and that we
-                    * thus should use the old method. If none of these
-                    * conditions match, we know that we need to load the very
-                    * old v1 format, which was in host order and had no
-                    * version tag. We use 'o' for old format, 'h' for host
-                    * order formats with version tag and 'n' for network
-                    * order formats with version tag.
-                    *
-                    * What a hack, but we don't want to have trouble loading
-                    * our database when upgrading! Eventually, we'll even
-                    * probably switch to a text format.
-                    */
-                   p = (u_int8_t *)&ver;
-                   if (p[0] == 0xff && p[1] == 0xff)
-                       format = 'n';
-                   else if (p[2] == 0xff && p[3] == 0xff)
-                       format = 'h';
-                   else
-                       format = 'o';
-
-                   if (format == 'n') {
-                       /* Load new network byte order database formats with
-                        * version tag support
-                        */
-                       syslog(LOG_NOTICE, "Loading network byte order "
-                               "database with version tag support");
-                       version = 0xFFFFFFFF - BYTEORDER_HOST32(ver);
-                       switch (version) {
-                       case 5:
-                           ok = db_load_v5(fh, lognum, logpos);
-                           break;
-                       default:
-                           ok = FALSE;
-                           syslog(LOG_NOTICE,
-                                   "Unknown database type (version %u)",
-                                   (unsigned int)version);
-                           break;
-                       }
-                   } else if (format == 'h') {
-                       /* Load older host byte order database formats with
-                        * version tag support
-                        */
-                       syslog(LOG_NOTICE, "Loading host byte order database"
-                               " with version tag support");
-                       version = 0xFFFFFFFF - ver;
-                       switch (version) {
-                       case 2:
-                           {
-                               long o_lognum;
-
-                               /* mmstatd 0.0.2, db v2 */
-                               ok = db_load_v2(fh, &o_lognum, logpos);
-                               *lognum = (u_int32_t)o_lognum;
-                               break;
-                           }
-                       case 3:
-                           {
-                               long o_lognum;
-
-                               /* mmstatd 0.0.3 db v3 */
-                               ok = db_load_v3(fh, &o_lognum, logpos);
-                               *lognum = (u_int32_t)o_lognum;
-                               break;
-                           }
-                       case 4:
-                           {
-                               long o_lognum;
-
-                               /* mmstatd 0.0.7 db v4 */
-                               ok = db_load_v4(fh, &o_lognum, logpos);
-                               *lognum = (u_int32_t)o_lognum;
-                               break;
-                           }
-                       default:
-                           ok = FALSE;
-                           syslog(LOG_NOTICE,
-                                   "Unknown database type (version %u)",
-                                   (unsigned int)version);
-                           break;
-                       }
-                   } else {
-                       /* Load the old host byte order database format
-                        * without version tag support
-                        */
-                       long o_lognum, o_logpos;
-
-                       /* Seek back to start since there was no version info
-                        * back then
-                        */
-                       syslog(LOG_NOTICE,
-                               "Loading very first format host byte order "
-                               " database without version tag support "
-                               "(it was more than time to upgrade :)");
-                       fseek(fh, 0, SEEK_SET);
-                       ok = db_load_v1(fh, &o_lognum, &o_logpos);
-                       *lognum = (u_int32_t)o_lognum;
-                       *logpos = (off_t)o_logpos;
-                   }
-               } else
-                   ok = FALSE;
-               (void) fclose(fh);
-               if (!ok)
-                   syslog(LOG_NOTICE,
-                           "db_load() - Error loading database (corrupt)");
-           } else
-               syslog(LOG_NOTICE, "db_load() - New database");
-       } else
-           DEBUG_PRINTF("db_load", "hashtable_init()");
-    } else
-       DEBUG_PRINTF("db_load", "pool_init()");
-}
-
-
-static bool
-db_load_v1(FILE *fh, long *lognum, long *logpos)
-{
-    struct key_node *knod = NULL;
-    u_int64_t hash;
-    unsigned char len;
-    bool ok = TRUE;
-
-    if (fread(lognum, sizeof(long), 1, fh) != 1 ||
-           fread(logpos, sizeof(long), 1, fh) != 1)
-       ok = FALSE;
-    while (ok) {
-       if (fread(&hash, sizeof(u_int64_t), 1, fh) == 1) {
-           if ((knod = (struct key_node *)pool_alloc(&key_pool, FALSE))) {
-               knod->entry.persistent = TRUE;
-               knod->processed = FALSE;
-               if (fread(&knod->entry.value, sizeof(int64_t), 1, fh) != 1
-                       || fread(&knod->entry.created, sizeof(time_t), 1,
-                           fh) != 1
-                       || fread(&knod->entry.modified, sizeof(time_t), 1,
-                           fh) != 1
-                       || fread(&knod->entry.uid, sizeof(uid_t), 1,
-                           fh) != 1
-                       || fread(&len, sizeof(unsigned char), 1, fh) != 1
-                       || fread(&knod->entry.key, len + 1, 1, fh) != 1)
-                   ok = FALSE;
-               else {
-                   if (!hashtable_link(&key_table, (hashnode_t *)knod,
-                               knod->entry.key, len + 1, TRUE)) {
-                       DEBUG_PRINTF("db_load_v1", "Duplicate key '%s'",
-                               knod->entry.key);
-                       knod = (struct key_node *)pool_free((pnode_t *)knod);
-                   }
-               }
-           } else
-               ok = FALSE;
-           if (!ok)
-               if (knod) pool_free((pnode_t *)knod);
-       } else
-           break;
-    }
-
-    return (ok);
-}
-
-
-static bool
-db_load_v2(FILE *fh, long *lognum, off_t *logpos)
-{
-    struct key_node *knod = NULL;
-    u_int64_t hash;
-    unsigned char len;
-    bool ok = TRUE;
-
-    if (fread(lognum, sizeof(long), 1, fh) != 1 ||
-           fread(logpos, sizeof(off_t), 1, fh) != 1)
-       ok = FALSE;
-    while (ok) {
-       if (fread(&hash, sizeof(u_int64_t), 1, fh) == 1) {
-           if ((knod = (struct key_node *)pool_alloc(&key_pool, FALSE))) {
-               knod->entry.persistent = TRUE;
-               knod->processed = FALSE;
-               if (fread(&knod->entry.value, sizeof(int64_t), 1, fh) != 1
-                       || fread(&knod->entry.created, sizeof(time_t), 1,
-                           fh) != 1
-                       || fread(&knod->entry.modified, sizeof(time_t), 1,
-                           fh) != 1
-                       || fread(&knod->entry.uid, sizeof(uid_t), 1,
-                           fh) != 1
-                       || fread(&len, sizeof(unsigned char), 1, fh) != 1
-                       || fread(&knod->entry.key, len + 1, 1, fh) != 1)
-                   ok = FALSE;
-               else {
-                   if (!hashtable_link(&key_table, (hashnode_t *)knod,
-                               knod->entry.key, len + 1, TRUE)) {
-                       DEBUG_PRINTF("db_load_v2", "Duplicate key '%s'",
-                               knod->entry.key);
-                       knod = (struct key_node *)pool_free((pnode_t *)knod);
-                   }
-               }
-           } else
-               ok = FALSE;
-           if (!ok)
-               if (knod) pool_free((pnode_t *)knod);
-       } else
-           break;
-    }
-
-    return (ok);
-}
-
-
-static bool
-db_load_v3(FILE *fh, long *lognum, off_t *logpos)
-{
-    struct key_node *knod = NULL;
-    u_int64_t hash;
-    size_t len;
-    bool ok = TRUE;
-
-    if (fread(lognum, sizeof(long), 1, fh) != 1 ||
-           fread(logpos, sizeof(off_t), 1, fh) != 1)
-       ok = FALSE;
-    while (ok) {
-       if (fread(&hash, sizeof(u_int64_t), 1, fh) == 1) {
-           if ((knod = (struct key_node *)pool_alloc(&key_pool, FALSE))) {
-               knod->entry.persistent = TRUE;
-               knod->processed = FALSE;
-               if (fread(&knod->entry.value, sizeof(int64_t), 1, fh) != 1
-                       || fread(&knod->entry.created, sizeof(time_t), 1,
-                           fh) != 1
-                       || fread(&knod->entry.modified, sizeof(time_t), 1,
-                           fh) != 1
-                       || fread(&knod->entry.uid, sizeof(uid_t), 1,
-                           fh) != 1
-                       || fread(&len, sizeof(size_t), 1, fh) != 1
-                       || fread(&knod->entry.key, len + 1, 1, fh) != 1)
-                   ok = FALSE;
-               else {
-                   if (!hashtable_link(&key_table, (hashnode_t *)knod,
-                               knod->entry.key, len + 1, TRUE)) {
-                       DEBUG_PRINTF("db_load_v3", "Duplicate key '%s'",
-                               knod->entry.key);
-                       knod = (struct key_node *)pool_free((pnode_t *)knod);
-                   }
-               }
-           } else
-               ok = FALSE;
-           if (!ok)
-               if (knod) pool_free((pnode_t *)knod);
-       } else
-           break;
-    }
-
-    return (ok);
-}
-
-
-static bool
-db_load_v4(FILE *fh, long *lognum, off_t *logpos)
-{
-    struct key_node *knod = NULL;
-    int64_t val;
-    size_t len;
-    bool ok = TRUE;
-
-    if (fread(lognum, sizeof(long), 1, fh) != 1 ||
-           fread(logpos, sizeof(off_t), 1, fh) != 1)
-       ok = FALSE;
-    while (ok) {
-       if (fread(&val, sizeof(int64_t), 1, fh) == 1) {
-           if ((knod = (struct key_node *)pool_alloc(&key_pool, FALSE))) {
-               knod->entry.persistent = TRUE;
-               knod->entry.value = val;
-               knod->processed = FALSE;
-               if (fread(&knod->entry.created, sizeof(time_t), 1, fh) != 1
-                       || fread(&knod->entry.modified, sizeof(time_t), 1,
-                           fh) != 1
-                       || fread(&knod->entry.uid, sizeof(uid_t), 1,
-                           fh) != 1
-                       || fread(&len, sizeof(size_t), 1, fh) != 1
-                       || fread(&knod->entry.key, len + 1, 1, fh) != 1)
-                   ok = FALSE;
-               else {
-                   if (!hashtable_link(&key_table, (hashnode_t *)knod,
-                               knod->entry.key, len + 1, TRUE)) {
-                       DEBUG_PRINTF("db_load_v4", "Duplicate key '%s'",
-                               knod->entry.key);
-                       knod = (struct key_node *)pool_free((pnode_t *)knod);
-                   }
-               }
-           } else
-               ok = FALSE;
-           if (!ok)
-               if (knod) pool_free((pnode_t *)knod);
-       } else
-           break;
-    }
-
-    return (ok);
-}
-
-
-/* This format is in architecture-independent network order, and uses
- * platform-independent word units instead of saving actual word sizes
- * corresponding to a particular object type,
- * (i.e. size_t, off_t, uid_t, time_t).
- */
-static bool
-db_load_v5(FILE *fh, u_int32_t *lognum, off_t *logpos)
-{
-    struct key_node *knod = NULL;
-    int64_t val64;
-    u_int32_t val32;
-    size_t len;
-    bool ok = FALSE;
-
-    if (fread(lognum, sizeof(u_int32_t), 1, fh) != 1 ||
-           fread(&val64, sizeof(u_int64_t), 1, fh) != 1)
-       return FALSE;
-
-    *lognum = BYTEORDER_HOST32(*lognum);
-    *logpos = (off_t)BYTEORDER_HOST64((u_int32_t)val64);
-
-    for (;;) {
-       /* Read and convert key current value */
-       if (fread(&val64, sizeof(u_int64_t), 1, fh) == 1) {
-           val64 = (int64_t)BYTEORDER_HOST64(val64);
-           if ((knod = (struct key_node *)pool_alloc(&key_pool, FALSE))) {
-
-               knod->entry.persistent = TRUE;
-               knod->entry.value = (int64_t)val64;
-               knod->processed = FALSE;
-
-               /* Creation time */
-               if (fread(&val32, sizeof(u_int32_t), 1, fh) != 1)
-                   break;
-               knod->entry.created = (time_t)BYTEORDER_HOST32(val32);
-
-               /* Modification time */
-               if (fread(&val32, sizeof(u_int32_t), 1, fh) != 1)
-                   break;
-               knod->entry.modified = (time_t)BYTEORDER_HOST32(val32);
-
-               /* Owner user id */
-               if (fread(&val32, sizeof(u_int32_t), 1, fh) != 1)
-                   break;
-               knod->entry.uid = (uid_t)BYTEORDER_HOST32(val32);
-
-               /* Key name string size */
-               if (fread(&val32, sizeof(u_int32_t), 1, fh) != 1)
-                   break;
-               len = (size_t)BYTEORDER_HOST32(val32);
-
-               /* Actual key name string, this obviously doesn't need any
-                * kind of conversion.
-                */
-               if (fread(&knod->entry.key, len + 1, 1, fh) != 1)
-                   break;
-
-               /* All entry loaded, link it in */
-               if (!hashtable_link(&key_table, (hashnode_t *)knod,
-                           knod->entry.key, len + 1, TRUE)) {
-                   syslog(LOG_NOTICE, "db_load_v5() - Duplicate key '%s'",
-                           knod->entry.key);
-                   (void) pool_free((pnode_t *)knod);
-               }
-
-               /* Set knod to NULL, this allows us to know to call
-                * pool_free() when above possible errors just break.
-                */
-               knod = NULL;
-
-           } else {
-               syslog(LOG_NOTICE, "db_load_v5() - Out of memory");
-               break;
-           }
-       } else {
-           /* All entries were valid, but there just aren't any more */
-           ok = TRUE;
-           break;
-       }
-    }
-
-    if (knod != NULL)
-       (void) pool_free((pnode_t *)knod);
-
-    return (ok);
-}
-
-
-/* This function syncs the memory db to disk with current sync info.
- * If save was successful, obsolete recovery logs are deleted.
- * We warn through syslog if the sync could not be performed.
- * If all is TRUE, all logs are deleted after sync.
- * The saved format is now platform independent and architecture independent.
- * This means that we save everything in network order, and that we don't use
- * platform dependent data types in the output, only fixed-sized words of
- * known length.
- */
-static void
-db_sync(u_int32_t lognum, off_t logpos, bool all)
-{
-    char old_db[256], new_db[256];
-    FILE *fh;
-    DIR *dir;
-    u_int32_t version = 0xFFFFFFFF - 5;
-    bool ok;
-    struct db_sync_iterator_udata data;
-
-    /* We use a technique which permits to retrieve the previous state of
-     * the db in case we could not save properly, using rename().
-     */
-    ok = TRUE;
-
-    snprintf(old_db, 255, "%s/mmstatd.db", CONF.ENV_DIR);
-    snprintf(new_db, 255, "%s/mmstatd.tdb", CONF.ENV_DIR);
-    syslog(LOG_NOTICE, "Synchronizing database to disk file '%s'", old_db);
-
-    /* Use stdio buffering since we are about to perform many small writes */
-    if ((fh = fopen(new_db, "wb")) != NULL) {
-       u_int64_t val64;
-       u_int32_t val32;
-
-       (void) fchmod(fileno(fh), 0600);
-       /* Write db version and current sync state */
-       version = BYTEORDER_NETWORK32(version);
-       val32 = BYTEORDER_NETWORK32(lognum);
-       val64 = BYTEORDER_NETWORK64((u_int64_t)logpos);
-       if (fwrite(&version, sizeof(u_int32_t), 1, fh) == 1 &&
-               fwrite(&val32, sizeof(u_int32_t), 1, fh) == 1 &&
-               fwrite(&val64, sizeof(u_int64_t), 1, fh) == 1) {
-           /* DB contents */
-           data.fh = fh;
-           data.ok = TRUE;
-           hashtable_iterate(&key_table, db_sync_iterator, &data);
-           ok = data.ok;
-       } else
-           ok = FALSE;
-
-       /* We always verified that fwrite(3) succeed, but we also must make
-        * sure that fsync(2) and close(2) do (the latter being called by
-        * fclose(3)).
-        */
-       if (ok) {
-           if (fflush(fh) != 0 || fsync(fileno(fh)) != 0)
-               ok = FALSE;
-       }
-       while (fclose(fh) != 0) {
-           if (errno != EINTR) {
-               ok = FALSE;
-               break;
-           }
-       }
-    } else
-       ok = FALSE;
-
-    if (ok) {
-       /* We are certain that the new file was properly written, we can now
-        * atomically replace the old database by the new one.
-        */
-       if (rename(new_db, old_db) == -1)
-           ok = FALSE;
-    }
-
-    if (!ok) {
-       /* Error while attempting to rename(), delete new saved file and keep
-        * old one, but log the error.
-        */
-       unlink(new_db);
-       syslog(LOG_NOTICE, "db_sync() - Error writing database!");
-    } else {
-       /* Scan for recovery logs and unlink obsolete ones */
-       if ((dir = opendir(CONF.ENV_DIR))) {
-           char *name, filename[256];
-           struct dirent *dire;
-           u_int32_t i;
-
-           while ((dire = readdir(dir))) {
-               name = dire->d_name;
-               if (log_match(name, "????????.log")) {
-                   i = (u_int32_t)strtoul(name, NULL, 10);
-                   if (all || i < lognum) {
-                       snprintf(filename, 255, "%s/%s", CONF.ENV_DIR, name);
-                       unlink(filename);
-                   }
-               }
-           }
-           closedir(dir);
-       }
-    }
-}
-
-
-static bool
-db_sync_iterator(hashnode_t *hnod, void *udata)
-{
-    struct key_node *knod = (struct key_node *)hnod;
-    struct db_sync_iterator_udata *data = udata;
-    FILE *fh = data->fh;
-
-    /* Only save persistent keys */
-    if (knod->entry.persistent) {
-       size_t len;
-       u_int32_t val32;
-       u_int64_t val64;
-
-       /* Default to false return value, so we can simply return on error.
-        * Returning with FALSE will cause the hashtable_t iteration to stop.
-        */
-       data->ok = FALSE;
-
-       /* Current value of key */
-       val64 = BYTEORDER_NETWORK64((u_int64_t)knod->entry.value);
-       if (fwrite(&val64, sizeof(u_int64_t), 1, fh) != 1)
-           return FALSE;
-
-       /* Creation time */
-       val32 = BYTEORDER_NETWORK32((u_int32_t)knod->entry.created);
-       if (fwrite(&val32, sizeof(u_int32_t), 1, fh) != 1)
-           return FALSE;
-
-       /* Last modification time */
-       val32 = BYTEORDER_NETWORK32((u_int32_t)knod->entry.modified);
-       if (fwrite(&val32, sizeof(u_int32_t), 1, fh) != 1)
-           return FALSE;
-
-       /* Key owner user id */
-       val32 = BYTEORDER_NETWORK32((u_int32_t)knod->entry.uid);
-       if (fwrite(&val32, sizeof(u_int32_t), 1, fh) != 1)
-           return FALSE;
-
-       /* Key name string size */
-       len = mm_strlen(knod->entry.key);
-       val32 = BYTEORDER_NETWORK32((u_int32_t)len);
-       if (fwrite(&val32, sizeof(u_int32_t), 1, fh) != 1)
-           return FALSE;
-
-       /* Key name string */
-       if (fwrite(knod->entry.key, len + 1, 1, fh) != 1)
-           return FALSE;
-
-       /* Everything ok, set success return value */
-       data->ok = TRUE;
-    }
-
-    return TRUE;
-}
-
-
-static void
-db_free(void)
-{
-    if (HASHTABLE_VALID(&key_table))
-       hashtable_destroy(&key_table, FALSE);
-    if (POOL_VALID(&key_pool))
-       pool_destroy(&key_pool);
-}
-
-
-/* This function loads the db, attempts to perform recovery processing the
- * logs, resyncs the db and unloads everything. This function is intended to
- * be executed when the logging daemon process is not running.
- */
-static void
-db_recover(void)
-{
-    int fd;
-    u_int32_t lognum;
-    off_t logpos;
-    int len, total;
-    char filename[256];
-    struct log_entry lentry[MAX_TRANSACT + 1];
-    bool ok;
-
-    syslog(LOG_NOTICE, "Recovering last db modifications from logs");
-
-    /* First obtain our last position in the last logfile so that we do not
-     * process logs which have already been applied to the db before last sync.
-     */
-    ok = FALSE;
-    snprintf(filename, 255, "%s/%s", CONF.ENV_DIR, "mmstatd.db");
-    db_load(&lognum, &logpos);
-
-    /* If any, start processing logs, but make sure to only start after
-     * lognum/logpos, if there are any remaining, since we are only
-     * performing recovery of unsynced pending logs.
-     */
-    snprintf(filename, 255, "%s/%08u.log", CONF.ENV_DIR, lognum);
-    total = 0;
-    if ((fd = open(filename, O_RDONLY)) != -1) {
-       if (logpos > 0)
-           (void) lseek(fd, logpos, SEEK_SET);
-       while ((len = logentries_read(-1, lentry, MAX_TRANSACT, &fd, &lognum,
-                       &logpos))) {
-           total += len;
-           if (!logentries_process(lentry, len, FALSE)) {
-               DEBUG_PRINTF("db_recover", "logentries_process()");
-               break;
-           }
-       }
-       (void) close(fd);
-    }
-
-    if (total > 0)
-       syslog(LOG_NOTICE, "Recovered %d log entries", total);
-    else
-       syslog(LOG_NOTICE, "No entries needed recovery");
-
-    /* Sync back db to disk and delete obsolete recovery logs */
-    lognum = 0;
-    logpos = 0;
-    db_sync(lognum, logpos, TRUE);
-    db_free();
-}
-
-
-/* key char array should be KEY_SIZE bytes in size */
-static void
-stats_write(int fd, const char *key)
-{
-    struct key_node *knod;
-
-    /* Sanity check */
-    if (key[KEY_SIZE - 1] == '\0') {
-       /* Verify if this consists of: '*' and/or '?' pattern, absolute
-        * key name or full report request
-        */
-       if (*key == '\0') {
-           /* Full statistics report request */
-           hashtable_iterate(&key_table, stats_write_iterator_full, &fd);
-       } else {
-           const char *ptr;
-
-           for (ptr = key; *ptr != '\0'; ptr++)
-               if (*ptr == '*' || *ptr == '?')
-                   break;
-           if (*ptr != '\0') {
-               struct stats_write_iterator_pattern_udata data;
-
-               /* Key pattern matching report request */
-               data.fd = fd;
-               data.pattern = key;
-               hashtable_iterate(&key_table, stats_write_iterator_pattern,
-                       &data);
-           } else {
-               /* Absolute key report request */
-               if ((knod = (struct key_node *)hashtable_lookup(&key_table,
-                               key, mm_strlen(key) + 1)) != NULL) {
-                   if (pipesend)
-                       write(fd, &knod->entry, sizeof(mmstatent_t));
-               }
-           }
-       }
-    }
-}
-
-
-static bool
-stats_write_iterator_full(hashnode_t *hnod, void *udata)
-{
-    struct key_node *knod = (struct key_node *)hnod;
-    int fd = *(int *)udata;
-
-    if (pipesend)
-       write(fd, &knod->entry, sizeof(mmstatent_t));
-
-    return pipesend;
-}
-
-
-static bool
-stats_write_iterator_pattern(hashnode_t *hnod, void *udata)
-{
-    struct key_node *knod = (struct key_node *)hnod;
-    struct stats_write_iterator_pattern_udata *data = udata;
-
-    if (pipesend) {
-       if (log_match(knod->entry.key, data->pattern))
-           write(data->fd, &knod->entry, sizeof(mmstatent_t));
-    }
-
-    return pipesend;
-}
-
-
-static void
-stats_rotate(const char *pattern, const char *prefix)
-{
-    char okey[KEY_SIZE + 1], nkey[KEY_SIZE + 1];
-
-    /* Sanity check */
-    if (pattern[KEY_SIZE - 1] == '\0' && prefix[KEY_SIZE - 1] == '\0') {
-       struct stats_rotate_iterator_process_udata data;
-
-       /* Because modifying a key requires to unlink and relink it to the
-        * table, and that the ordering of the iteration is undefined, we
-        * have to make sure not to attempt to process the same entry more
-        * than once, which could still be matching with the pattern.
-        * We therefore use a boolean flag (processed) to prevent this.
-        * Our iterator functions use it.
-        */
-       data.pattern = pattern;
-       data.prefix = prefix;
-       data.okey = okey;
-       data.nkey = nkey;
-       hashtable_iterate(&key_table, stats_rotate_iterator_process, &data);
-       hashtable_iterate(&key_table, stats_rotate_iterator_clear, NULL);
-    }
-}
-
-
-static bool
-stats_rotate_iterator_process(hashnode_t *hnod, void *udata)
-{
-    struct key_node *knod = (struct key_node *)hnod;
-    struct stats_rotate_iterator_process_udata *data = udata;
-
-    /* We make sure to not process already processed keys, and to restore the
-     * old key if the renaming process causes a duplicate.
-     */
-    if (knod->processed == FALSE && knod->entry.persistent &&
-           log_match(knod->entry.key, data->pattern)) {
-       knod->processed = TRUE;
-       mm_memcpy(data->okey, knod->entry.key, KEY_SIZE);
-       hashtable_unlink(&key_table, (hashnode_t *)knod);
-       snprintf(data->nkey, KEY_SIZE - 1, "%s%s", data->prefix,
-               knod->entry.key);
-       mm_memcpy(knod->entry.key, data->nkey, KEY_SIZE);
-       if (!hashtable_link(&key_table, (hashnode_t *)knod, knod->entry.key,
-                   mm_strlen(data->nkey) + 1, TRUE)) {
-           /* Would cause a duplicate, restore entry */
-           syslog(LOG_NOTICE, "stats_rotate() - Rename of key '%s' to '%s' \
-would cause a duplicate", data->okey, data->nkey);
-           mm_memcpy(knod->entry.key, data->okey, KEY_SIZE);
-           hashtable_link(&key_table, (hashnode_t *)knod, knod->entry.key,
-                   mm_strlen(data->okey), FALSE);
-       }
-    }
-
-    return TRUE;
-}
-
-
-/* ARGSUSED */
-static bool
-stats_rotate_iterator_clear(hashnode_t *hnod, void *udata)
-{
-    struct key_node *knod = (struct key_node *)hnod;
-
-    knod->processed = FALSE;
-
-    return TRUE;
-}
-
-
-int
-main(int argc, char **argv)
-{
-    char *conf_file = "/usr/local/etc/mmstatd.conf", *tmp;
-    int ret = 0, ngids;
-    uid_t uid;
-    gid_t *gids;
-    long facility;
-    cres_t cres;
-    carg_t *cargp;
-    carg_t cargs[] = {
-       {CAT_STR, CAF_NONE, 1, 31, "USER", CONF.USER},
-       {CAT_STR, CAF_NONE, 1, 255, "GROUPS", CONF.GROUPS},
-       {CAT_STR, CAF_NONE, 1, 31, "LOG_FACILITY", CONF.LOG_FACILITY},
-       {CAT_STR, CAF_NONE, 1, 255, "PID_FILE", CONF.PID_FILE},
-       {CAT_STR, CAF_NONE, 1, 255, "LOCK_FILE", CONF.LOCK_FILE},
-       {CAT_STR, CAF_NONE, 1, 255, "LOG_SOCKET", CONF.LOG_SOCKET},
-       {CAT_STR, CAF_NONE, 1, 255, "STAT_SOCKET", CONF.STAT_SOCKET},
-       {CAT_STR, CAF_NONE, 1, 127, "ENV_DIR", CONF.ENV_DIR},
-       {CAT_STR, CAF_NONE, 1, 31, "LOG_GROUP", CONF.LOG_GROUP},
-       {CAT_STR, CAF_NONE, 1, 31, "STAT_GROUP", CONF.STAT_GROUP},
-       {CAT_VAL, CAF_NONE, 1, 99999999, "SYNC_INTERVAL",
-           &CONF.SYNC_INTERVAL},
-       {CAT_VAL, CAF_NONE, 0, 99999999, "SYNC_BYTES", &CONF.SYNC_BYTES},
-       {CAT_VAL, CAF_NONE, 1, 99999999, "MAX_LOGSIZE", &CONF.MAX_LOGSIZE},
-       {CAT_VAL, CAF_NONE, 0, 9999, "STATS_RATE", &CONF.STATS_RATE},
-       {CAT_VAL, CAF_NONE, 1, 9999, "STATS_TIME", &CONF.STATS_TIME},
-       {CAT_END, CAF_NONE, 0, 0, NULL, NULL}
-    };
-    cmap_t cmap[] = {
-       {"LOG_AUTH", LOG_AUTH},
-       {"LOG_AUTHPRIV", LOG_AUTHPRIV},
-       {"LOG_CRON", LOG_CRON},
-       {"LOG_DAEMON", LOG_DAEMON},
-       {"LOG_FTP", LOG_FTP},
-       {"LOG_LPR", LOG_LPR},
-       {"LOG_MAIL", LOG_MAIL},
-       {"LOG_NEWS", LOG_NEWS},
-       {"LOG_SYSLOG", LOG_SYSLOG},
-       {"LOG_USER", LOG_USER},
-       {"LOG_UUCP", LOG_UUCP},
-       {NULL, 0}
-    };
-
-    /* Set defaults */
-    mm_strcpy(CONF.USER, "mmstatd");
-    mm_strcpy(CONF.GROUPS, "mmstat,staff");
-    mm_strcpy(CONF.LOG_FACILITY, "LOG_AUTHPRIV");
-    mm_strcpy(CONF.PID_FILE, "/var/mmstatd/mmstatd.pid");
-    mm_strcpy(CONF.LOCK_FILE, "/var/mmstatd/mmstatd.lock");
-    mm_strcpy(CONF.LOG_SOCKET, "/var/mmstatd/mmstatd_log.sock");
-    mm_strcpy(CONF.STAT_SOCKET, "/var/mmstatd/mmstatd_stat.sock");
-    mm_strcpy(CONF.ENV_DIR, "/var/mmstatd");
-    mm_strcpy(CONF.LOG_GROUP, "mmstat");
-    mm_strcpy(CONF.STAT_GROUP, "staff");
-    CONF.SYNC_INTERVAL = 1800;
-    CONF.SYNC_BYTES = 4096;
-    CONF.MAX_LOGSIZE = 1048576;
-    CONF.STATS_RATE = 5;
-    CONF.STATS_TIME = 10;
-
-    /* Read config file */
-    if ((tmp = getenv("MMSTATCONF")))
-       conf_file = tmp;
-    if (argc == 2)
-       conf_file = argv[1];
-    if (!mmreadcfg(&cres, cargs, conf_file)) {
-       /* Error parsing configuration file, report which */
-       printf("\nError parsing '%s'\n", conf_file);
-       printf("Error  : %s\n", mmreadcfg_strerr(cres.CR_Err));
-       if (*(cres.CR_Data)) printf("Data   : %s\n", cres.CR_Data);
-       if ((cargp = cres.CR_Keyword) != NULL) {
-           printf("Keyword: %s\n", cargp->CA_Keyword);
-           printf("Minimum: %ld\n", cargp->CA_Min);
-           printf("Maximum: %ld\n", cargp->CA_Max);
-       }
-       if (cres.CR_Line != -1)
-           printf("Line   : %d\n", cres.CR_Line);
-       printf("\n");
-       exit(-1);
-    }
-
-    if (!mmmapstring(cmap, CONF.LOG_FACILITY, &facility)) {
-       printf("\nUnknown syslog facility %s\n\n", CONF.LOG_FACILITY);
-       exit(-1);
-    }
-    openlog(DAEMON_NAME, LOG_PID | LOG_NDELAY, facility);
-
-#ifndef NODROPPRIVS
-    if ((getuid())) {
-       printf("\nOnly the super user may start this daemon\n\n");
-       syslog(LOG_NOTICE, "* Only superuser can start me");
-       exit(-1);
-    }
-#else /* NODROPPRIVS */
-    if ((getuid()) == 0) {
-       printf("\nCompiled with NODROPPRIVS, refusing to run as uid 0\n\n");
-       syslog(LOG_NOTICE, "* NODROPPRIVS, refusing to run as uid 0");
-       exit(-1);
-    }
-#endif /* !NODROPPRIVS */
-
-    if (!lock_check(CONF.LOCK_FILE)) {
-       printf("\nmmstatd already running\n\n");
-       exit(-1);
-    }
-    /* Post parsing */
-    if ((uid = mmgetuid(CONF.USER)) == -1) {
-       printf("\nUnknown USER '%s'\n\n", CONF.USER);
-       exit(-1);
-    }
-    if (!(gids = mmgetgidarray(&ngids, CONF.GROUPS))) {
-       printf("\nOne or more of following GROUPS unknown: '%s'\n\n",
-               CONF.GROUPS);
-       exit(-1);
-    }
-    if ((CONF.log_group = mmgetgid(CONF.LOG_GROUP)) == -1) {
-       printf("\nUnknown LOG_GROUP '%s'\n\n", CONF.LOG_GROUP);
-       exit(-1);
-    }
-    if ((CONF.stat_group = mmgetgid(CONF.STAT_GROUP)) == -1) {
-       printf("\nUnknown STAT_GROUP '%s'\n\n", CONF.STAT_GROUP);
-       exit(-1);
-    }
-    CONF.max_logsize = (off_t)CONF.MAX_LOGSIZE;
-
-    /* Initialization */
-    librarian_pid = logger_pid = -1;
-    pipefds[0] = pipefds[1] = -1;
-
-    printf("\r\n+++ %s (%s)\r\n\r\n", DAEMON_NAME, DAEMON_VERSION);
-
-    /* Drop root privileges */
-    if (mmdropprivs(uid, gids, ngids)) {
-       mmfreegidarray(gids);
-       /* Launch the librarian process */
-       if ((librarian_pid = process_spawn(librarian_init, NULL, TRUE))
-               == -1) {
-           DEBUG_PRINTF("main", "process_spawn(librarian)");
-           ret = -1;
-       }
-    } else {
-       ret = -1;
-       DEBUG_PRINTF("main", "mmdropprivs()");
-    }
-
-    closelog();
-
-    return (ret);
-}
-
-
-static int
-librarian_init(void *args)
-{
-    int fd;
-
-    syslog(LOG_NOTICE, "Librarian process started");
-
-    /* Write PID file */
-    if ((fd = open(CONF.PID_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0600)) != -1) {
-       char str[16];
-       snprintf(str, 15, "%d", getpid());
-       write(fd, str, mm_strlen(str));
-       close(fd);
-    } else
-       DEBUG_PRINTF("librarian_init", "Cannot write pid file");
-
-    /* Perform recovery */
-    db_recover();
-
-    /* Prepare our notification pipe */
-    if (!(pipe(pipefds))) {
-
-       /* Start the logger process */
-       if ((logger_pid = process_spawn(logger_init, NULL, FALSE)) != -1) {
-           char filename[256];
-           u_int32_t lognum;
-           off_t logpos;
-           int ufd, lfd, max;
-
-           close(pipefds[1]);
-           pipefds[1] = -1;
-
-           if ((ufd = unix_init(CONF.STAT_SOCKET, CONF.stat_group, 0660, 16,
-                           TRUE, TRUE)) != -1) {
-               /* Because we recovered, lognum and logpos will be 0 */
-               db_load(&lognum, &logpos);
-               /* Make sure that we open for reading the file that the logger
-                * opened for writing
-                */
-               snprintf(filename, 255, "%s/00000000.log", CONF.ENV_DIR);
-               max = 10;
-               while ((lfd = open(filename, O_RDONLY)) == -1 && max) {
-                   sleep(1);
-                   max--;
-               }
-               if (lfd != -1) {
-                   /* Finally start main loop */
-                   librarian_main(pipefds[0], ufd, lfd, &lognum, &logpos);
-                   close(lfd);
-               } else
-                   DEBUG_PRINTF("librarian_init", "open(%s)", filename);
-               db_sync(lognum, logpos, FALSE);
-               db_free();
-               close(ufd);
-               unlink(CONF.STAT_SOCKET);
-           } else
-               DEBUG_PRINTF("librarian_init",
-                       "unix_init(%s)", CONF.STAT_SOCKET);
-       } else
-           DEBUG_PRINTF("librarian_init", "process_spawn(logger)");
-
-       close(pipefds[0]);
-       pipefds[0] = -1;
-    } else
-       DEBUG_PRINTF("librarian_init", "pipe()");
-
-    unlink(CONF.PID_FILE);
-
-    /* Kill logger daemon */
-    if (logger_pid != -1) {
-       int status;
-       if (!kill(logger_pid, SIGTERM)) waitpid(logger_pid, &status, 0);
-    }
-
-    syslog(LOG_NOTICE, "Exiting librarian");
-    return (0);
-}
-
-
-/* Here consists of the main librarian server process. It's function consists
- * in following the logs created by the logger process in an ASYNC manner,
- * and process them, managing the database. It also performs total SYNC of the
- * database to disk at fixed intervals, cleaning up obsolete recovery logs.
- */
-static void
-librarian_main(int pfd, int ufd, int lfd, u_int32_t *lognum, off_t *logpos)
-{
-    time_t otim;
-    int len;
-    long secs;
-    struct log_entry entries[MAX_TRANSACT + 1];
-    struct pollfd fds[] = {
-       {pfd, POLLIN, 0},
-       {ufd, POLLIN, 0},
-    };
-    struct limitrate lr;
-
-#ifndef __GLIBC__
-    setproctitle("Librarian process");
-#endif
-
-    secs = 0;  /* Used to time delay between syncs */
-    LR_INIT(&lr, CONF.STATS_RATE, CONF.STATS_TIME, time(NULL));
-    for (;;) {
-       otim = time(NULL);
-       if (poll(fds, 2, 60000) > 0) {
-           /* Process more log entries if any */
-           if (fds[0].revents & POLLIN) {
-               if ((len = logentries_read(pfd, entries, MAX_TRANSACT, &lfd,
-                               lognum, logpos)))
-                   logentries_process(entries, len, TRUE);
-           }
-           /* Verify if we obtain a report request connection */
-           if (fds[1].revents & POLLIN) {
-               socklen_t addrl;
-               struct sockaddr addr;
-               int sfd;
-               char key[KEY_SIZE + 1], key2[KEY_SIZE + 1], c;
-
-               /* Accept connection and send status report */
-               addrl = sizeof(struct sockaddr);
-               pipesend = TRUE;
-               if ((sfd = accept(ufd, &addr, &addrl)) != -1) {
-                   struct pollfd fds2[] = {
-                       {sfd, POLLIN, 0}
-                   };
-
-                   /* Make sure to drop connection immediately if rate
-                    * was exceeded
-                    */
-                   if (CONF.STATS_RATE == 0 ||
-                           lr_allow(&lr, 1, time(NULL), TRUE)) {
-                       if (pipesend) write(sfd, "+", 1);
-                       if (poll(fds2, 1, 250) == 1) {
-                           if (fds2[0].revents & POLLIN) {
-                               if (read(sfd, &c, 1) == 1) {
-                                   if (c == 's') {
-                                       if (read(sfd, key, KEY_SIZE) ==
-                                               KEY_SIZE) {
-                                           shutdown(sfd, SHUT_RD);
-                                           if (pipesend) stats_write(sfd, key);
-                                       }
-                                   } else if (c == 'r') {
-                                       if (read(sfd, key, KEY_SIZE) ==
-                                               KEY_SIZE &&
-                                               read(sfd, key2, KEY_SIZE) ==
-                                               KEY_SIZE) {
-                                           stats_rotate(key, key2);
-                                           /* Force immediate db sync */
-                                           secs += CONF.SYNC_INTERVAL;
-                                       }
-                                   } else
-                                       syslog(LOG_NOTICE,
-                                       "librarian_main() - invalid req");
-                               } else
-                                   DEBUG_PRINTF("librarian_main",
-                                           "read(%d)", sfd);
-                           }
-                       }
-                   } else if (pipesend)
-                       write(sfd, "-", 1);
-                   close(sfd);
-               }
-           }
-       }
-       /* Verify if it's time for a sync */
-       secs += (time(NULL) - otim);
-       if (secs > CONF.SYNC_INTERVAL) {
-           secs = 0;
-           db_sync(*lognum, *logpos, FALSE);
-       }
-    }
-    /* NOTREACHED */
-}
-
-
-static int
-logger_init(void *args)
-{
-    char filename[256];
-    u_int32_t lognum;
-    off_t logpos;
-    int ufd, lfd;
-
-    syslog(LOG_NOTICE, "Logger process started");
-
-    close(pipefds[0]);
-    pipefds[0] = -1;
-    lognum = 0;
-    logpos = 0;
-
-    if ((ufd = unix_init(CONF.LOG_SOCKET, CONF.log_group, 0220, 0, FALSE,
-                   TRUE)) != -1) {
-       snprintf(filename, 255, "%s/00000000.log", CONF.ENV_DIR);
-       if ((lfd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) != -1) {
-           fsync(lfd);
-           logger_main(pipefds[1], ufd, lfd, &lognum, &logpos);
-           close(lfd);
-       } else
-           DEBUG_PRINTF("logger_init", "open(%s)", filename);
-       close(ufd);
-       unlink(CONF.LOG_SOCKET);
-    } else
-       DEBUG_PRINTF("logger_init", "unix_init(%s)", CONF.LOG_SOCKET);
-    close(pipefds[1]);
-    pipefds[1] = -1;
-
-    syslog(LOG_NOTICE, "Exiting logger");
-    return (0);
-}
-
-
-/* Here consists of the logger process server, using unix domain sockets.
- * It's function is to obtain single as well as transaction locked requests
- * from the various processes, and to generate recovery logs and sync them
- * to disk as soon as possible. It is of major importance that this process
- * perform all required sanity checking on the input datagrams, thus preventing
- * packet attacks resulting in undefined behavior. We do not allow the client
- * to generate STAT_NEWFILE or STAT_TRANSACT control packets, and we ensure
- * that they only send valid packet lengths, particularly valid key string
- * as well. Morover, we make sure to set the euid of the datagram originator.
- *
- * Note that we obtain the packet in host endian order, which we dispatch to
- * logentries_write(), which will perform required convertion to network
- * byte order.
- *
- * XXX eventually add AF_LOCAL user credential checking here...
- */
-static void
-logger_main(int pfd, int ufd, int lfd, u_int32_t *lognum, off_t *logpos)
-{
-    uid_t uid, euid;
-    int len, l, i, i2, t;
-    char *tmp;
-    struct log_entry aentries[MAX_TRANSACT + 2], *entries;
-    struct pollfd fds[] = {
-       {ufd, POLLIN, 0}
-    };
-
-#ifndef __GLIBC__
-    setproctitle("Logger process");
-#endif
-
-    /* Prepare transaction header and footer entries, the footer will need
-     * to be copied earlier in the buffer when the transaction packet is
-     * smaller than MAX_TRANSACT, to allow using one write() only.
-     */
-    entries = &(aentries[1]);
-    mm_memclr(aentries, sizeof(struct log_entry));
-    aentries->type = STAT_TRANSACT;
-    mm_memcpy(&(aentries[MAX_TRANSACT + 1]), aentries,
-           sizeof(struct log_entry));
-    aentries->un.transact.begin = TRUE;
-
-    for (;;) {
-       if (poll(fds, 1, -1) > 0) {
-           if (fds[0].revents & POLLIN) {
-               /* New packet to log, may consist of a single operation or
-                * of transaction-protected atomic operations array.
-                */
-               if ((len = recvfrom(ufd, entries,
-                               sizeof(struct log_entry) * MAX_TRANSACT,
-                               MSG_WAITALL, NULL, NULL)) > 0) {
-                   /* XXX Eventually obtain packet sender credentials */
-                   uid = euid = 0;
-                   /* Perform some sanity checking, first verify packet size */
-                   l = 0;
-                   i2 = 1;
-                   if ((len >= sizeof(struct log_entry)) &&
-                           (len <= sizeof(struct log_entry) * MAX_TRANSACT) &&
-                           ((len % sizeof(struct log_entry)) == 0)) {
-                       /* Now verify packet type and key C string validity
-                        * XXX Should eventually use cleaner code here
-                        */
-                       l = len / sizeof(struct log_entry);
-                       for (i2 = 0; i2 < l; i2++) {
-                           t = (int)entries[i2].type;
-                           if (t != STAT_UPDATE && t != STAT_RESET &&
-                                   t != STAT_DELETE)
-                               break;
-                           tmp = entries[i2].key;
-                           for (i = 0; i < KEY_SIZE; i++)
-                               if (tmp[i] == '\0' || tmp[i] < 33 ||
-                                       tmp[i] == '%')
-                                   break;
-                           if (i < 1 || i > KEY_SIZE - 1 ||
-                                   (tmp[i] != '\0' &&
-                                    (tmp[i] < 33 || tmp[i] == '%')))
-                               break;
-                           /* Make sure that packet originator uid cannot be
-                            * spoofed
-                            */
-                           entries[i2].uid = (u_int32_t)euid;
-                       }
-                   }
-                   if (i2 == l) {
-                       /* This packet at least won't crash us, it will
-                        * simply be ignored if invalid to this point.
-                        * Perform some magic before writing the entry if
-                        * it consists of a transaction.
-                        */
-                       if (len == sizeof(struct log_entry)) {
-                           if (!logentries_write(pfd, entries, 1, &lfd,
-                                       lognum, logpos))
-                               syslog(LOG_NOTICE,
-                                       "logger_main() - Error writing logs!");
-                       } else {
-                           t = len / sizeof(struct log_entry);
-                           if (t < MAX_TRANSACT)
-                               mm_memcpy(&entries[t],
-                                       &aentries[MAX_TRANSACT + 1],
-                                       sizeof(struct log_entry));
-                           t += 2;
-                           if (!logentries_write(pfd, aentries, t, &lfd,
-                                       lognum, logpos))
-                               syslog(LOG_NOTICE,
-                                      "logger_main() - Error writing logs!");
-                       }
-                   } else
-                       syslog(LOG_NOTICE,
-                              "Illegal packet from uid %d, euid %d, %d bytes",
-                              uid, euid, len);
-               } else
-                   DEBUG_PRINTF("logger_main", "recvfrom(%d)", ufd);
-           }
-       }
-    }
-    /* NOTREACHED */
-}
diff --git a/mmsoftware/mmstatd/src/mmstatd.conf.5 b/mmsoftware/mmstatd/src/mmstatd.conf.5
deleted file mode 100644 (file)
index a32b39d..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-.\" $Id: mmstatd.conf.5,v 1.5 2004/05/05 23:59:58 mmondor Exp $
-.\"
-.\" Copyright (C) 2002-2004, Matthew Mondor
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software written by Matthew Mondor.
-.\" 4. The name of Matthew Mondor may not be used to endorse or promote
-.\"    products derived from this software without specific prior written
-.\"    permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-.\" IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd 11 Dec, 2002
-.Dt MMSTATD.CONF 5
-.Os
-.Sh NAME
-.Nm mmstatd.conf
-.Nd
-.Xr mmstatd.conf 5
-configuration file for mmstatd and mmstat
-.Sh DESCRIPTION
-The
-.Nm /usr/local/etc/mmstatd.conf
-file may contain one or more keyword/value pairs per line, empty lines or
-comments.  A ';' or '#' character causes all other characters to be considered
-as a comment, and to be ignored, until the end of the current line. It is
-very important to enclose the value for a keyword in double quotes ('"'
-characters) if the following characters are found in it: ';', '#', space and
-tab. Here are documented the various possible keywords and their
-allowed values, as well as their defaults, and mmstatd/mmstat relation.
-.Pp
-.Nm These are both used by mmstatd and mmstat:
-.Pp
-.Bl -tag -width XXXXXXXX -offset indent -compact
-.It Nm LOG_SOCKET Ar "file"
-Location of statistics update request socket, to which the logger process
-of
-.Nm mmstatd
-listens to.
-.Pp
-.It Nm STAT_SOCKET Ar "file"
-Location of statistics report request socket, to which the librarian process
-of
-.Nm mmstatd listens to.
-.El
-.Pp
-.Nm These are only used by mmstatd:
-.Pp
-.Bl -tag -width XXXXXXXX -offset indent -compact
-.It Nm USER Ar "user"
-Unprivileged user service should run as.
-.Pp
-.It Nm GROUPS Ar "group,..."
-Groups mmstatd should be part of, separated by commas, without spaces.
-The groups specified
-for
-.Ar LOG_GROUP
-and
-.Ar STAT_GROUP
-should also be specified here.
-.Pp
-.It Nm LOG_FACILITY Ar "facility"
-Syslog facility which should be used for error logging. Should normally be
-one of
-.Sy LOG_AUTH LOG_AUTHPRIV LOG_CRON LOG_DAEMON LOG_FTP LOG_KERN LOG_LPR
-.Sy LOG_MAIL LOG_NEWS LOG_SYSLOG LOG_USER LOG_UUCP
-, see
-.Xr syslog 3
-man page for more information.
-.Pp
-.It Nm PID_FILE Ar "file"
-Location where mmstatd writes it's pid file. This consists of a small file
-holding the process ID of
-.Nm mmstatd
-which can be used by scripts or the administrator to kill the daemon properly.
-.Pp
-.It Nm LOCK_FILE Ar "file"
-Location of mmstatd lock file, this is only used to make sure that only
-one copy of the service is running, otherwise this could lead to database
-corruption.
-.Pp
-.It Nm ENV_DIR Ar "directory"
-Location where database and recovery logs are internally, automatically stored
-and managed by
-.Nm mmstatd
-daemon.
-.Pp
-.It Nm LOG_GROUP Ar "group"
-.Ar LOG_SOCKET
-is created with permission mode 220. This permits users of the specified
-group to perform statistic update requests, using the
-.Xr mmstat 3
-library interface. Don't forget to also specify this group name into
-.Ar GROUPS
-variable.
-.Pp
-.It Nm STAT_GROUP Ar "group"
-.Ar STAT_SOCKET
-is created with permission mode 660. This permits users of the specified
-group to obtain statistic reports or to rotate statistics using the
-.Xr mmstat 3
-library interface, or
-.Xr mmstat 8
-utility. Don't forget to also specify this group name into
-.Ar GROUPS 
-variable.
-.Pp
-.It Nm SYNC_INTERVAL Ar "seconds"
-Specifies the interval in seconds at which the statistics db will be
-synchronized to disk. This delay can be long enough, as a good log-based
-recovery technique is used in case system crashed between two sync events.
-.Pp
-.It Nm SYNC_BYTES Ar "bytes"
-Maximum number of bytes to write to recovery logs before forcing a sync
-with physical media (using fdatasync()). 0 Can be specified to force a sync
-after every new entry; Higher values may cause some of the last update
-requests before a crash to be lost but will be more efficient.
-.Pp
-.It Nm MAX_LOGSIZE Ar "bytes"
-Maximum size of a recovery log file, in bytes. When reaching that size
-internal rotation to other files is performed. Logs are internally maintained
-and cleaned up as necessary by mmstatd and are not user serviceable.
-.Pp
-.It Nm STATS_RATE Ar "times"
-Maximum number of times Unix stream connections to
-.Ar STAT_SOCKET
-can be performed within
-.Ar STATS_TIME
-period. This prevents an application from requesting a large number of full
-reports thus potentially preventing the librarian part of
-.Nm mmstatd
-to peform its vital tasks. As a general rule reports are not requested
-frequently. If necessary, 0 can be specified for no limit, and care should be
-taken to choose an adequate
-.Ar STAT_GROUP
-to restrict access.
-.Pp
-.It Nm STATS_TIME Ar "seconds"
-Period in seconds during which a maximum of
-.Ar STATS_RATE
-connections are allowed to occur.
-.El
-.Sh DEFAULTS
-The following defaults are used:
-.Pp
-.Bd -literal -offset indent -compact
-USER            mmstatd
-GROUPS          mmstat,staff
-LOG_FACILITY    LOG_AUTHPRIV
-PID_FILE        "/var/mmstatd/mmstatd.pid"
-LOCK_FILE       "/var/mmstatd/mmstatd.lock"
-LOG_SOCKET      "/var/mmstatd/mmstatd_log.sock"
-STAT_SOCKET     "/var/mmstatd/mmstatd_stat.sock"
-ENV_DIR         "/var/mmstatd"
-LOG_GROUP       mmstat
-STAT_GROUP      staff
-SYNC_INTERVAL   1800
-SYNC_BYTES      4096
-MAX_LOGSIZE     1048576
-STATS_RATE      5
-STATS_TIME      10
-.Ed
-.Sh AUTHOR
-mmstat and related daemon and library were written by Matthew Mondor,
-and are Copyright (c) 2002-2004, Matthew Mondor, All rights reserved.
-It originally was written for the mmftpd and mmmail suite of daemons by the
-same author.
-.Sh FILES
-.Bl -tag -width XXXXXXXXXXXXXXXXXXXX -compact
-.It Pa <mmstat.h>
-Headerfile used both by
-.Nm mmstatd
-daemon and
-.Nm mmstat
-utility, defining related
-.Ar MAX_TRANSACT
-variable.
-.Pp
-.It Pa /usr/local/etc/mmstatd.conf
-Configuration file for both
-.Nm mmstatd
-daemon and
-.Nm mmstat
-utility. (This file)
-.El
-.Sh SEE ALSO
-.Xr mmstat 3 ,
-.Xr mmstat 8 ,
-.Xr mmstatd 8 ,
-.Xr syslog 3 ,
-.Xr fdatasync 2 ,
-.Xr fsync 2 .
-.Sh BUGS
-Please report any bug to mmondor@accela.net
diff --git a/mmsoftware/mmstatd/src/mmstatd.h b/mmsoftware/mmstatd/src/mmstatd.h
deleted file mode 100644 (file)
index 99ddc00..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/* $Id: mmstatd.h,v 1.10 2004/06/01 23:52:43 mmondor Exp $ */
-
-/*
- * Copyright (C) 2002-2004, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-
-#ifndef MMSTATD_H
-#define MMSTATD_H
-
-
-
-
-#include <sys/types.h>
-
-#include <mmtypes.h>
-#include <mmpool.h>
-#include <mmhash.h>
-#include <mmstat.h>
-
-
-
-
-#define DAEMON_NAME    "mmstatd"
-#define DAEMON_VERSION "0.0.9/mmondor"
-
-
-
-
-struct key_node {
-    hashnode_t node;
-    mmstatent_t entry;
-    bool processed;
-};
-
-struct db_sync_iterator_udata {
-    FILE *fh;
-    bool ok;
-};
-
-struct stats_write_iterator_pattern_udata {
-    int fd;
-    const char *pattern;
-};
-
-struct stats_rotate_iterator_process_udata {
-    const char *pattern;
-    const char *prefix;
-    char *okey, *nkey;
-};
-
-
-
-
-static pid_t   process_spawn(int (*)(void *), void *, bool);
-static void    sighandler(int);
-static bool    lock_check(const char *);
-static int     unix_init(const char *, gid_t, mode_t, int, bool, bool);
-static bool    log_match(const char *, const char *);
-static bool    logentries_write(int, struct log_entry *, int, int *,
-                       u_int32_t *, off_t *);
-static bool    logentry_read(int, struct log_entry *, int *,
-                       u_int32_t *, off_t *);
-static int     logentries_read(int, struct log_entry *, int, int *,
-                       u_int32_t *, off_t *);
-static bool    logentry_process(struct log_entry *, bool);
-static bool    logentry_process_iterator(hashnode_t *, void *);
-static bool    logentries_process(struct log_entry *, int, bool);
-/* static void logentry_debug(char, struct log_entry *); */
-static void    db_load(u_int32_t *, off_t *);
-static bool    db_load_v1(FILE *, long *, long *);
-static bool    db_load_v2(FILE *, long *, off_t *);
-static bool    db_load_v3(FILE *, long *, off_t *);
-static bool    db_load_v4(FILE *, long *, off_t *);
-static bool    db_load_v5(FILE *, u_int32_t *, off_t *);
-static void    db_sync(u_int32_t, off_t, bool);
-static bool    db_sync_iterator(hashnode_t *, void *);
-static void    db_free(void);
-static void    db_recover(void);
-static void    stats_write(int, const char *);
-static bool    stats_write_iterator_full(hashnode_t *, void *);
-static bool    stats_write_iterator_pattern(hashnode_t *, void *);
-static void    stats_rotate(const char *, const char *);
-static bool    stats_rotate_iterator_process(hashnode_t *, void *);
-static bool    stats_rotate_iterator_clear(hashnode_t *, void *);
-
-int main(int, char **);
-
-static int     librarian_init(void *);
-static void    librarian_main(int, int, int, u_int32_t *, off_t *);
-static int     logger_init(void *);
-static void    logger_main(int, int, int, u_int32_t *, off_t *);
-
-
-
-
-
-
-#endif
diff --git a/mmsoftware/mmsucom/GNUmakefile b/mmsoftware/mmsucom/GNUmakefile
deleted file mode 100644 (file)
index 9f66a3f..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-# $Id: GNUmakefile,v 1.1 2004/09/24 19:40:04 mmondor Exp $
-
-MMLIB_PATH := ../mmlib
-
-MMLIBS := $(addprefix ${MMLIB_PATH}/,mmarch.o mmpool.o mmlog.o mmstring.o)
-OBJS := $(addprefix ,mmsucom.o mmsucomd.o)
-BINS := $(addprefix ,mmsucom mmsucomd)
-CFLAGS += -Wall
-
-all: $(BINS)
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I${MMLIB_PATH} -o $@ $<
-
-
-mmsucom: $(MMLIBS) mmsucom.o
-       cc -o $@ mmsucom.o -lc $(MMLIBS)
-
-mmsucomd: $(MMLIBS) mmsucomd.o
-       cc -o $@ mmsucomd.o -lc $(MMLIBS)
-
-
-install: all
-       install -cs -o 0 -g 0 -m 500 mmsucomd /usr/local/sbin
-       install -cs -o 0 -g 0 -m 550 mmsucom /usr/local/sbin
-
-clean:
-       rm -f $(BINS) $(OBJS) $(MMLIBS)
diff --git a/mmsoftware/mmsucom/Makefile b/mmsoftware/mmsucom/Makefile
deleted file mode 100644 (file)
index b41b25a..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# $Id: Makefile,v 1.1 2002/12/11 10:16:51 mmondor Exp $
-
-CC = gcc
-MAKE = make
-#STRIP = strip
-
-CFLAGS += -Wall
-
-INCDIR = -I../mmlib -I/usr/include -I/usr/pkg/include -I.
-LIBDIR = -L/usr/local/lib -L/usr/lib -L/lib -L/usr/pkg/lib
-
-LIBS = ../mmlib/libmmondor.a -lc
-
-OBJS = mmsucomd.o
-
-
-
-CCOBJ = $(CC) $(CFLAGS) -c $(INCDIR)
-
-
-
-
-mmsucomd: $(OBJS)
-       $(CC) $(CFLAGS) -o mmsucomd $(INCDIR) $(LIBDIR) $(OBJS) $(LIBS)
-       $(CC) $(CFLAGS) -o mmsucom $(INCDIR) $(LIBDIR) mmsucom.c $(LIBS)
-#      $(STRIP) -s mmsucomd
-
-
-
-
-clean:
-       -rm -f $(OBJS) mmsucomd mmsucom
-
-
-mmsucomd.o:
-       $(CCOBJ) mmsucomd.c
-
diff --git a/mmsoftware/mmsucom/README b/mmsoftware/mmsucom/README
deleted file mode 100644 (file)
index 754c25a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-$Id: README,v 1.1 2002/12/11 10:16:51 mmondor Exp $
-
-
-This consists of a little sudo replacement, a very simple one actually.
-It is meant to allow some users right to execute specific commands without
-user-provided arguments, under the priviledges of another user, like uid 0.
-
-I mainly use it so that users on NetBSD desktop systems can mount and umount
-floppies and cdrom. To execute a command, user has to have write access to
-the mmsucomd socket, thus being of the required group to access the file.
-That user may then invoque commands using keys, as set in /etc/mmsucomd.conf,
-via the mmsucom client.
-
-Here consists of a little example:
-
-/etc/mmsucomd.conf
-------------------
-m_cd   root    wheel   /sbin/mount /cdrom
-um_cd  root    wheel   /sbin/umount /cdrom
-m_fl   root    wheel   /sbin/mount /floppy
-um_fl  root    wheel   /sbin/umount /floppy
-page   root    wheel   /bin/ksh -c "echo -ne '\007' >/dev/ttyE0"
-
-$ mmsucom m_cd
-$ cd /cdrom
-
-This mostly consists of a quick hack, although it should be pretty safe
-when well setup by the administrator. 
diff --git a/mmsoftware/mmsucom/mmsucom.c b/mmsoftware/mmsucom/mmsucom.c
deleted file mode 100644 (file)
index 1dfec4e..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/* $Id: mmsucom.c,v 1.5 2005/05/14 04:58:17 mmondor Exp $ */
-
-/*
- * Copyright (C) 2002-2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-
-/* HEADERS */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include <mmtypes.h>
-#include <mmstring.h>
-
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmsucom.c,v 1.5 2005/05/14 04:58:17 mmondor Exp $");
-
-
-
-
-/* DEFINITIONS */
-
-/* Where socket should be */
-#define REQSOCKET      "/var/run/mmsucomd.sock"
-
-struct request {
-    u_int64_t id;
-};
-
-int main(int, char **);
-
-
-
-
-/* FUNCTIONS */
-
-int
-main(int argc, char **argv)
-{
-    int sock;
-    struct sockaddr_un addr;
-    socklen_t addrl;
-    struct request req;
-
-    if (argc == 2) {
-       if ((sock = socket(AF_LOCAL, SOCK_DGRAM, 0)) != -1) {
-           mm_strncpy(addr.sun_path, REQSOCKET, 100);
-           addr.sun_family = AF_UNIX;
-           addrl = sizeof(struct sockaddr_un);
-           req.id = mm_strhash64(argv[1]);
-           if ((sendto(sock, &req, sizeof(struct request), 0,
-                           (struct sockaddr *)&addr, addrl)) !=
-                   sizeof(struct request))
-               printf("\nError sending to mmsucomd.sock\n\n");
-           close(sock);
-       } else
-           printf("\nError at socket() creation\n\n");
-    } else
-       printf("\nUsage: mmsucom <commandkey>\n\n");
-
-    exit(0);
-}
diff --git a/mmsoftware/mmsucom/mmsucomd.c b/mmsoftware/mmsucom/mmsucomd.c
deleted file mode 100644 (file)
index 9a97c76..0000000
+++ /dev/null
@@ -1,453 +0,0 @@
-/* $Id: mmsucomd.c,v 1.10 2005/05/14 04:58:17 mmondor Exp $ */
-
-/*
- * Copyright (C) 2002-2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software written by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-
-/* HEADERS */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/uio.h>
-#include <poll.h>
-#include <syslog.h>
-#include <signal.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include <mmtypes.h>
-#include <mmlist.h>
-#include <mmpool.h>
-#include <mmstring.h>
-
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmsucomd.c,v 1.10 2005/05/14 04:58:17 mmondor Exp $");
-
-
-
-
-/* DEFINITIONS */
-
-/* For syslog */
-#define SERVERNAME     "mmsucomd"
-/* Where pid file should go */
-#define PIDFILE                "/var/run/mmsucomd.pid"
-/* Config file location */
-#define CONFFILE       "/usr/local/etc/mmsucomd.conf"
-/* Where socket should be */
-#define REQSOCKET      "/var/run/mmsucomd.sock"
-#define REQGROUP       100     /* Group that can send reqs */
-#define MAX_RATE       5       /* Rate we execute commands */
-
-struct request {
-    u_int64_t id;
-};
-
-struct conf_node {
-    pnode_t node;
-    u_int64_t id;
-    int uid, gid;
-    char command[256];
-};
-
-
-
-
-/* PROTOTYPES */
-
-static pid_t spawn_process(int (*)(void *), void *);
-static bool drop_privs(int, int);
-static void sighandler(int);
-static int unix_init(char *, int, int, int);
-static bool conf_read(void);
-static void exec_command(struct conf_node *);
-
-int main(void);
-
-static int sucomd_init(void *);
-static void sucomd_main(int);
-
-
-
-
-/* GLOBALS */
-
-static pid_t sucomd_pid;
-
-/* This is set to FALSE when a process receives a SIGTERM */
-static bool run = TRUE, conf = FALSE;
-
-/* Configuration */
-static pool_t cpool;
-static list_t clist;
-
-
-
-
-/* FUNCTIONS */
-
-static
-pid_t spawn_process(int (*function)(void *), void *params)
-{
-    pid_t pid = -1;
-    int fd;
-
-    /* Create new process */
-    if (!(pid = fork())) {
-       struct sigaction act;
-
-       /* Child */
-       setsid();
-       chdir("/");
-       umask(0);
-
-       /* Make sure that stdin, stdout and stderr are safe */
-       if ((fd = open("/dev/null", O_RDWR)) != -1) {
-           dup2(fd, 0);
-           dup2(fd, 1);
-           dup2(fd, 2);
-           if (fd > 2)
-               close(fd);
-       }
-
-       /* Setup our break handler */
-       act.sa_handler = sighandler;
-       act.sa_flags = SA_NOCLDWAIT;
-       sigemptyset(&act.sa_mask);
-       sigaction(SIGTERM, &act, NULL);
-       sigaction(SIGHUP, &act, NULL);
-       sigaction(SIGCHLD, &act, NULL);
-
-       /* Signals we want to ignore */
-       signal(SIGTTOU, SIG_IGN);
-       signal(SIGTTIN, SIG_IGN);
-       signal(SIGTSTP, SIG_IGN);
-       /*signal(SIGPIPE, SIG_IGN); */
-
-       /* Simply call the wanted child function */
-       exit(function(params));
-
-    }
-
-    /* Parent */
-    return (pid);
-}
-
-
-static bool
-drop_privs(int uid, int gid)
-{
-    int cuid, cgid;
-
-    cuid = getuid();
-    cgid = getgid();
-
-    if (cuid != uid || cgid != gid) {
-       if (!cuid) {
-           /* We are root and thus can/must switch */
-           if ((!(setgid(gid))) && (!(setuid(uid))))
-               return (TRUE);
-       }
-    } else
-       /* We already were running from the proper user and group */
-       return (TRUE);
-
-    return (FALSE);
-}
-
-
-static void
-sighandler(int sig)
-{
-    switch (sig) {
-    case SIGTERM:
-       syslog(LOG_NOTICE, "Received SIGTERM, cleaning up");
-       run = FALSE;
-       break;
-    case SIGHUP:
-       syslog(LOG_NOTICE, "Received SIGHUP, reading config");
-       conf = TRUE;
-       break;
-    case SIGCHLD:
-       {
-           int s = 0;
-
-           while ((wait3(&s, WNOHANG, NULL)) > 0) ;
-       }
-       break;
-    default:
-       syslog(LOG_NOTICE, "Signal handler catched unexpected signal");
-       break;
-    }
-}
-
-
-static int
-unix_init(char *name, int group, int mode, int backlog)
-{
-    int sock;
-    struct sockaddr_un sau;
-
-    /* Open public UNIX domain socket */
-    if ((sock = socket(AF_LOCAL, SOCK_DGRAM, 0)) != -1) {
-       mm_strncpy(sau.sun_path, name, 100);
-       sau.sun_family = AF_UNIX;
-       if (bind(sock, (struct sockaddr *)&sau, sizeof(struct sockaddr_un))
-               != -1) {
-           if (!chmod(name, mode)) {
-               if (!chown(name, -1, group)) {
-                   return (sock);
-               } else
-                   syslog(LOG_NOTICE, "unix_init() - fchown()");
-           } else
-               syslog(LOG_NOTICE, "unix_init() - fchmod()");
-       } else
-           syslog(LOG_NOTICE, "unix_init() - bind()");
-       close(sock);
-    } else
-       syslog(LOG_NOTICE, "unix_init() - socket()");
-
-    return (-1);
-}
-
-
-static bool conf_read(void)
-{
-    u_int64_t id;
-    bool ok = FALSE;
-    FILE *fh;
-    int uid, gid, l;
-    char buf[256], *args[5];
-    struct passwd *tuid;
-    struct group *tgid;
-    struct conf_node *cnod;
-
-    DLIST_INIT(&clist);
-    if (POOL_VALID(&cpool))
-       pool_destroy(&cpool);
-    if (pool_init(&cpool, "cpool", malloc, free, NULL, NULL,
-               sizeof(struct conf_node), 64, 0, 0)) {
-       if ((fh = fopen(CONFFILE, "r")) != NULL) {
-           ok = TRUE;
-           l = 0;
-           while ((fgets(buf, 256, fh))) {
-               l++;
-               /* id  user  group  command line */
-               if (mm_strspl(args, buf, 4, '\t') == 4) {
-                   if ((tuid = getpwnam(args[1])) != NULL) {
-                       uid = tuid->pw_uid;
-                       if ((tgid = getgrnam(args[2])) != NULL) {
-                           gid = tgid->gr_gid;
-                           id = mm_strhash64(args[0]);
-                           DLIST_FOREACH(&clist, cnod)
-                               if (cnod->id == id)
-                                   break;
-                           if (cnod == NULL) {
-                               if ((cnod = (struct conf_node *)pool_alloc(
-                                               &cpool, FALSE))) {
-                                   cnod->id = id;
-                                   cnod->uid = uid;
-                                   cnod->gid = gid;
-                                   mm_strncpy(cnod->command, args[3], 255);
-                                   DLIST_APPEND(&clist, (node_t *)cnod);
-                               } else
-                                   syslog(LOG_NOTICE,
-                                           "conf_read() - pool_alloc()");
-                           } else
-                               syslog(LOG_NOTICE,
-                                       "conf_read() - Duplicate key '%s'",
-                                       args[0]);
-                       } else
-                           syslog(LOG_NOTICE,
-                                   "conf_read() - Unknown group '%s'",
-                                   args[2]);
-                   } else
-                       syslog(LOG_NOTICE,
-                               "conf_read() - Unknown user '%s'", args[1]);
-               } else
-                   syslog(LOG_NOTICE,
-                           "conf_read() - Malformed config file at line %d",
-                           l);
-           }
-       } else
-           syslog(LOG_NOTICE, "conf_read() - open(%s)", CONFFILE);
-       fclose(fh);
-    } else
-       syslog(LOG_NOTICE, "conf_read() - pool_init()");
-
-    return (ok);
-}
-
-
-static void
-exec_command(struct conf_node *cnod)
-{
-    pid_t pid;
-
-    if ((pid = fork()) == 0) {
-       extern char **environ;
-       char *args[] = {
-           "sh", "-c", cnod->command, NULL
-       };
-
-       if (drop_privs(cnod->uid, cnod->gid)) {
-           execve("/bin/sh", args, environ);
-           /* If we get here an error occured */
-           syslog(LOG_NOTICE, "exec_command() - Error executing '%s'",
-                   cnod->command);
-       } else
-           syslog(LOG_NOTICE, "exec_command() - drop_privs(%d,%d)",
-                   cnod->uid, cnod->gid);
-       exit(0);
-    } else if (pid == -1)
-       syslog(LOG_NOTICE, "exec_command() - fork()");
-}
-
-
-int
-main(void)
-{
-    openlog(SERVERNAME, LOG_PID, LOG_AUTH);
-
-    if ((sucomd_pid = spawn_process(sucomd_init, NULL)) == -1)
-       syslog(LOG_NOTICE, "main() - spawn_process(sucomd_init)");
-
-    closelog();
-    exit(0);
-}
-
-
-static int
-sucomd_init(void *args)
-{
-    int fd, ufd;
-
-    /* Write PID file */
-    if ((fd = open(PIDFILE, O_CREAT | O_TRUNC | O_WRONLY,
-                   S_IRUSR | S_IWUSR, 0600)) != -1) {
-       char str[16];
-       snprintf(str, 15, "%d", getpid());
-       write(fd, str, mm_strlen(str));
-       close(fd);
-    } else
-       syslog(LOG_NOTICE, "* sucomd_init() - Can't write pid file");
-
-    /* Read configuration */
-    if (conf_read()) {
-       /* Init and start main loop */
-       if ((ufd = unix_init(REQSOCKET, REQGROUP, 0660, 1)) != -1) {
-           syslog(LOG_NOTICE, "Launching sucomd");
-           sucomd_main(ufd);
-           close(ufd);
-           unlink(REQSOCKET);
-       } else
-           syslog(LOG_NOTICE, "sucomd_init() - Can't create socket '%s'",
-                   REQSOCKET);
-    } else
-       syslog(LOG_NOTICE, "sucomd_init() - Can't read config file '%s'",
-               CONFFILE);
-
-    if (POOL_VALID(&cpool))
-       pool_destroy(&cpool);
-    unlink(PIDFILE);
-
-    return (0);
-}
-
-
-/* Here consists of the main librarian server process. It's function consists
- * in following the logs created by the logger process in an ASYNC manner,
- * and process them, managing the database. It also performs total SYNC of the
- * database to disk at fixed intervals, cleaning up obsolete recovery logs.
- */
-static void
-sucomd_main(int ufd)
-{
-    int len;
-    time_t otim, tim;
-    struct request req;
-    struct conf_node *cnod;
-    struct pollfd fds[] = {
-       {ufd, POLLIN, 0},
-    };
-
-    otim = time(NULL);
-    conf = FALSE;
-    while (run) {
-       if (conf) {
-           conf = FALSE;
-           if (!conf_read()) {
-               syslog(LOG_NOTICE,
-                       "sucomd_main() - Couldn't reload config! Exiting");
-               break;
-           }
-       }
-       if (poll(fds, 1, -1) > 0) {
-           if (fds[0].revents & POLLIN) {
-               /* A packet arrived, perform some sanity checking and
-                * process it
-                */
-               if ((len = recvfrom(ufd, &req, sizeof(struct request),
-                               MSG_WAITALL, NULL, NULL)) ==
-                       sizeof(struct request)) {
-                   if ((tim = time(NULL)) > otim + MAX_RATE) {
-                       otim = tim;
-                       DLIST_FOREACH(&clist, cnod)
-                           if (cnod->id == req.id)
-                               break;
-                       if (cnod != NULL)
-                           exec_command(cnod);
-                       else
-                           syslog(LOG_NOTICE,
-                               "sucomd_main() - Received invalid request id");
-                   } else
-                       syslog(LOG_NOTICE,
-                          "sucomd_main() - Ignored request exceeding rate");
-               }
-           }
-       }
-    }
-}
diff --git a/mmsoftware/mmsucom/mmsucomd.conf b/mmsoftware/mmsucom/mmsucomd.conf
deleted file mode 100644 (file)
index 9bcd858..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-m_cd   root    wheel   /sbin/mount /cdrom
-um_cd  root    wheel   /sbin/umount /cdrom
-m_fl   root    wheel   /sbin/mount /floppy
-um_fl  root    wheel   /sbin/umount /floppy
-page   root    wheel   /bin/ksh -c "echo -ne '\007' >/dev/ttyE0"
diff --git a/mmsoftware/stringtest/GNUmakefile b/mmsoftware/stringtest/GNUmakefile
deleted file mode 100644 (file)
index 0b2748f..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# $Id: GNUmakefile,v 1.1 2004/05/02 11:24:20 mmondor Exp $
-
-MMLIBS := $(addprefix ../mmlib/,mmstring.o)
-
-OBJS := stringtest.o
-
-CFLAGS += -Wall -DDEBUG -g
-
-
-all: stringtest
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I../mmlib -o $@ $<
-
-stringtest: $(MMLIBS) $(OBJS)
-       cc -o $@ $(OBJS) -lc $(MMLIBS)
-
-clean:
-       rm -f stringtest $(OBJS) $(MMLIBS)
diff --git a/mmsoftware/stringtest/stringtest.c b/mmsoftware/stringtest/stringtest.c
deleted file mode 100644 (file)
index a8ba547..0000000
+++ /dev/null
@@ -1,706 +0,0 @@
-/* $Id: stringtest.c,v 1.5 2004/05/31 20:28:28 mmondor Exp $ */
-
-/*
- * Program to test the mmstring(3) library
- * Copyright (c) 2004, Matthew Mondor,
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <mmtypes.h>
-#include <mmstring.h>
-
-
-
-#define CALL(f)                        (void) printf("%s\n", #f); f()
-#define ASSERT(c)              if (!(c)) error(__func__, __LINE__, #c, c);
-#define CMPCOLS(a, b, c)       comp_cols(__func__, __LINE__, (a), (b), (c));
-#define CMPBYTES(a, b, c)      comp_bytes(__func__, __LINE__, (a), (b), (c));
-
-
-
-int main(void);
-static void error(const char *, int, const char *, int);
-static void comp_cols(const char *, int, char **, char **, int);
-static void comp_bytes(const char *, int, const void *, int, size_t);
-static void test_strcmp(void);
-static void test_straspl(void);
-static void test_strasplq(void);
-static void test_cmdparse(void);
-static void test_strcat(void);
-static void test_strchr(void);
-static void test_strcpy(void);
-static void test_strdup(void);
-static void test_strcasecmp(void);
-static void test_strlen(void);
-static void test_strncat(void);
-static void test_strnchr(void);
-static void test_strncmp(void);
-static void test_strncpy(void);
-static void test_strndup(void);
-static void test_strncasecmp(void);
-static void test_strnlen(void);
-static void test_strnrchr(void);
-static void test_strrchr(void);
-static void test_strspl(void);
-static void test_strlower(void);
-static void test_strupper(void);
-static void test_strpack32(void);
-static void test_htol(void);
-static void test_strrev(void);
-static void test_strhash64(void);
-static void test_memhash64(void);
-static void test_memhash32(void);
-static void test_memcasehash32(void);
-static void test_memcasecmp(void);
-static void test_memset(void);
-static void test_memcmp(void);
-static void test_memcpy(void);
-static void test_memmove(void);
-
-
-
-int main(void)
-{
-    CALL(test_strcmp);
-    CALL(test_straspl);
-    CALL(test_strasplq);
-    CALL(test_cmdparse);
-    CALL(test_strcat);
-    CALL(test_strchr);
-    CALL(test_strcpy);
-    CALL(test_strdup);
-    CALL(test_strcasecmp);
-    CALL(test_strlen);
-    CALL(test_strncat);
-    CALL(test_strnchr);
-    CALL(test_strncmp);
-    CALL(test_strncpy);
-    CALL(test_strndup);
-    CALL(test_strncasecmp);
-    CALL(test_strnlen);
-    CALL(test_strnrchr);
-    CALL(test_strrchr);
-    CALL(test_strspl);
-    CALL(test_strlower);
-    CALL(test_strupper);
-    CALL(test_strpack32);
-    CALL(test_htol);
-    CALL(test_strrev);
-    CALL(test_strhash64);
-    CALL(test_memhash64);
-    CALL(test_memhash32);
-    CALL(test_memcasehash32);
-    CALL(test_memcasecmp);
-    CALL(test_memset);
-    CALL(test_memcmp);
-    CALL(test_memcpy);
-    CALL(test_memmove);
-
-    exit(EXIT_SUCCESS);
-}
-
-
-/* Useful for your custom ASSERT() macro */
-static void error(const char *func, int line, const char *cond, int res)
-{
-    /* We definitely don't want to abort(3), only to report error to stderr
-     * and exit(3) with EXIT_FAILURE code, which is why we use our own
-     * assertion macro.
-     */
-    (void) fprintf(stderr, "%s:%d - if (%s) == %d\n", func, line, cond, res);
-    exit(EXIT_FAILURE);
-}
-
-/* Useful to make sure that the result strings parsed by mm_str*spl()
- * functions are exact
- */
-static void comp_cols(const char *func, int line, char **cols1, char **cols2,
-       int many)
-{
-    int i;
-
-    ASSERT(cols1 != NULL && cols2 != NULL);
-
-    for (i = 0; i < many; i++) {
-       if (mm_strcmp(cols1[i], cols2[i]) != 0) {
-           (void) fprintf(stderr,
-                          "%s:%d - (cols1[%d](%s) != cols2[%d](%s))\n",
-                          func, line, i, cols1[i], i, cols2[i]);
-           exit(EXIT_FAILURE);
-       }
-    }
-}
-
-static void comp_bytes(const char *func, int line, const void *buf,
-       int c, size_t size)
-{
-    const unsigned char *ptr, *toptr;
-
-    ASSERT(buf != NULL && size != 0);
-
-    for (ptr = toptr = buf, toptr += size; ptr < toptr && *ptr == c; ptr++) ;
-    if (ptr != toptr) {
-       (void) fprintf(stderr, "%s:%d - (%p[%d] != '%c')\n",
-                      func, line, buf, ((int)ptr - (int)buf), c);
-       exit(EXIT_FAILURE);
-    }
-}
-
-static void test_strcmp(void)
-{
-    char *str = "String", *str2 = "Strin", *str3 = "string";
-
-    ASSERT(mm_strcmp(str, str) == 0);
-    ASSERT(mm_strcmp(str, str2) != 0);
-    ASSERT(mm_strcmp(str2, str) != 0);
-    ASSERT(mm_strcmp(str, str3) != 0);
-}
-
-static void test_straspl(void)
-{
-    char str[] = "this is\ta \t\t test\t  as you can see. ";
-    char str2[] = "this is\ta \t\t test\t  as you can see. ";
-    char str3[] = "this is\ta \t\t test\t  as you can see. ";
-    char str4[] = "and  another test!";
-    char *cols[9];
-    char *cstr[] = {
-       "this",
-       "is",
-       "a",
-       "test",
-       "as",
-       "you",
-       "can",
-       "see."
-    };
-    char *cstr2[] = {
-       "and",
-       "another",
-       "test!"
-    };
-    int v;
-
-    v = mm_straspl(cols, str, 8);
-    ASSERT(v == 8);
-    CMPCOLS(cols, cstr, v);
-
-    v = mm_straspl(cols, str2, 7);
-    ASSERT(v == 7);
-    CMPCOLS(cols, cstr, v);
-
-    v = mm_straspl(cols, str3, 9);
-    ASSERT(v == 8);
-    CMPCOLS(cols, cstr, v);
-
-    v = mm_straspl(cols, str4, 2);
-    ASSERT(v == 2);
-    CMPCOLS(cols, cstr2, v);
-}
-
-static void test_strasplq(void)
-{
-    char str[] = "this is\ta  \t'test1 test2'\t\t  as you can see. ";
-    char str2[] = "this is\ta  \t'test1 test2'\t\t  as you can see. ";
-    char str3[] = "this is\ta  \t'test1 test2'\t\t  as you can see. ";
-    char str4[] = "And another\r\nhello";
-    char str5[] = "And another\nhello";
-    char str6[] = "And another\nhello";
-    char str7[] = "this is\ta  \t'test1 test2\t\t  as you can see. ";
-    char str8[] = "this is 'a \n test\r ahah' yet\n again";
-    char *cols[9];
-    char *cstr[] = {
-       "this",
-       "is",
-       "a",
-       "test1 test2",
-       "as",
-       "you",
-       "can",
-       "see."
-    };
-    char *cstr2[] = {
-       "And",
-       "another"
-    };
-    int v;
-
-    v = mm_strasplq(cols, str, 8);
-    ASSERT(v == 8);
-    CMPCOLS(cols, cstr, v);
-
-    v = mm_strasplq(cols, str2, 7);
-    ASSERT(v == 7);
-    CMPCOLS(cols, cstr, v);
-
-    v = mm_strasplq(cols, str3, 9);
-    ASSERT(v == 8);
-    CMPCOLS(cols, cstr, v);
-
-    v = mm_strasplq(cols, str4, 8);
-    ASSERT(v == 2);
-    CMPCOLS(cols, cstr2, v);
-
-    v = mm_strasplq(cols, str5, 3);
-    ASSERT(v == 2);
-    CMPCOLS(cols, cstr2, v);
-
-    v = mm_strasplq(cols, str6, 1);
-    ASSERT(v == 1);
-    CMPCOLS(cols, cstr2, v);
-
-    v = mm_strasplq(cols, str7, 8);
-    ASSERT(v == -1);
-
-    v = mm_strasplq(cols, str8, 8);
-    ASSERT(v == -1);
-}
-
-static void test_cmdparse(void)
-{
-    char str[] = "/bin/ls -l '/home/some user' /\n";
-    char str2[] = "ls -l";
-    char *cstr[] = {
-       "ls",
-       "-l",
-       "/home/some user",
-       "/"
-    };
-    char *argv[5], *path;
-    int argc;
-
-    ASSERT(mm_cmdparse(&path, &argc, argv, str, 5) == TRUE);
-    ASSERT(mm_strcmp(path, "/bin/ls") == 0);
-    ASSERT(argc == 4);
-    CMPCOLS(argv, cstr, argc);
-
-    ASSERT(mm_cmdparse(&path, &argc, argv, str2, 5) != TRUE);
-}
-
-static void test_strcat(void)
-{
-    char *str = "Matthew ", *str2 = "Mondor";
-    char dstr[32], *tmp;
-
-    *dstr = '\0';
-    ASSERT(mm_strcat(dstr, str) != NULL);
-    ASSERT(mm_strcmp(dstr, str) == 0);
-    ASSERT(mm_strcat(dstr, str2) != NULL);
-    ASSERT(mm_strcmp(dstr, "Matthew Mondor") == 0);
-
-    *dstr = '\0';
-    ASSERT((tmp = mm_strcat(dstr, str)) != NULL);
-    ASSERT(mm_strcmp(dstr, str) == 0);
-    ASSERT(mm_strcat(tmp, str2) != NULL);
-    ASSERT(mm_strcmp(dstr, "Matthew Mondor") == 0);
-}
-
-static void test_strchr(void)
-{
-    char *str = "String-t";
-
-    ASSERT(mm_strchr(str, 't') == &str[1]);
-    ASSERT(mm_strchr(str, 'z') == NULL);
-}
-
-static void test_strcpy(void)
-{
-    char *str = "Matthew ", *str2 = "Mondor";
-    char dstr[32], *tmp;
-
-    *dstr = '\0';
-    ASSERT((tmp = mm_strcpy(dstr, str)) != NULL);
-    ASSERT(mm_strcmp(dstr, str) == 0);
-    ASSERT(mm_strcpy(tmp, str2) != NULL);
-    ASSERT(mm_strcmp(dstr, "Matthew Mondor") == 0);
-}
-
-#define STR "Some string"
-static void test_strdup(void)
-{
-    char *new;
-
-    ASSERT((new = _mm_strdup(STR)) != NULL);
-    ASSERT(mm_strcmp(STR, new) == 0);
-    free(new);
-}
-#undef STR
-
-static void test_strcasecmp(void)
-{
-    char *str = "String", *str2 = "Strin", *str3 = "string";
-
-    ASSERT(mm_strcasecmp(str, str) == 0);
-    ASSERT(mm_strcasecmp(str, str2) != 0);
-    ASSERT(mm_strcasecmp(str2, str) != 0);
-    ASSERT(mm_strcasecmp(str, str3) == 0);
-    ASSERT(mm_strcasecmp(str3, str) == 0);
-}
-
-static void test_strlen(void)
-{
-    ASSERT(mm_strlen("String") == 6);
-}
-
-static void test_strncat(void)
-{
-    char *str = "Matthew ", *str2 = "Mondor";
-    char dstr[32], *tmp;
-
-    *dstr = '\0';
-    ASSERT(mm_strncat(dstr, str, 31) != NULL);
-    ASSERT(mm_strcmp(dstr, str) == 0);
-    ASSERT(mm_strncat(dstr, str2, 31 - 8) != NULL);
-    ASSERT(mm_strcmp(dstr, "Matthew Mondor") == 0);
-
-    *dstr = '\0';
-    ASSERT((tmp = mm_strncat(dstr, str, 31)) != NULL);
-    ASSERT(mm_strcmp(dstr, str) == 0);
-    ASSERT(mm_strncat(tmp, str2, 31 - 8) != NULL);
-    ASSERT(mm_strcmp(dstr, "Matthew Mondor") == 0);
-
-    *dstr = '\0';
-    ASSERT(mm_strncat(dstr, str, 3) != NULL);
-    ASSERT(mm_strlen(dstr) != 3);
-}
-
-static void test_strnchr(void)
-{
-    char *str = "String";
-    size_t len = mm_strlen(str);
-
-    ASSERT(mm_strnchr(str, 't', len) == &str[1]);
-    ASSERT(mm_strnchr(str, 'z', len) == NULL);
-    ASSERT(mm_strnchr(str, 'i', 3) == NULL);
-    ASSERT(*(mm_strnchr(str, 'i', 4)) == 'i');
-    ASSERT(mm_strnchr(str, 'S', 0) == NULL);
-}
-
-static void test_strncmp(void)
-{
-    char *str = "String", *str2 = "Strin", *str3 = "string";
-
-    ASSERT(mm_strncmp(str, str2, 10) != 0);
-    ASSERT(mm_strncmp(str, str2, 5) == 0);
-    ASSERT(mm_strncmp(str2, str, 5) == 0);
-    ASSERT(mm_strncmp(str, str2, 6) != 0);
-    ASSERT(mm_strncmp(str2, str, 6) != 0);
-    ASSERT(mm_strncmp(str2, str, 10) != 0);
-    ASSERT(mm_strncmp(str, str3, 6) != 0);
-}
-
-static void test_strncpy(void)
-{
-    char dstr[32], *str = "Matthew ", *str2 = "Mondor";
-    size_t len;
-
-    ASSERT((len = mm_strncpy(dstr, str, 31)) == mm_strlen(str));
-    ASSERT(mm_strcmp(dstr, str) == 0);
-    ASSERT(mm_strncpy(&dstr[len], str2, 31 - len) == mm_strlen(str2));
-    ASSERT(mm_strcmp(dstr, "Matthew Mondor") == 0);
-    ASSERT(mm_strncpy(dstr, str, 3) == 3);
-    ASSERT(mm_strlen(dstr) == 3);
-}
-
-#define STR "some string"
-static void test_strndup(void)
-{
-    char *new;
-
-    ASSERT((new = mm_strndup(STR, 11)) != NULL);
-    ASSERT(mm_strcmp(STR, new) == 0);
-    free(new);
-
-    ASSERT((new = mm_strndup(STR, 8)) != NULL);
-    ASSERT(mm_strncmp(STR, new, 8) == 0);
-    ASSERT(mm_strlen(new) == 8);
-    free(new);
-}
-#undef STR
-
-static void test_strncasecmp(void)
-{
-    char *str = "String", *str2 = "Strin", *str3 = "string";
-
-    ASSERT(mm_strncasecmp(str, str2, 10) != 0);
-    ASSERT(mm_strncasecmp(str, str2, 5) == 0);
-    ASSERT(mm_strncasecmp(str2, str, 5) == 0);
-    ASSERT(mm_strncasecmp(str, str2, 6) != 0);
-    ASSERT(mm_strncasecmp(str2, str, 6) != 0);
-    ASSERT(mm_strncasecmp(str2, str, 10) != 0);
-    ASSERT(mm_strncasecmp(str, str3, 6) == 0);
-}
-
-static void test_strnlen(void)
-{
-    char *str = "String";
-
-    ASSERT(mm_strnlen(str, 6) == 6);
-    ASSERT(mm_strnlen(str, 31) == 6);
-    ASSERT(mm_strnlen(str, 5) == 5);
-    ASSERT(mm_strnlen(str, 0) == 0);
-}
-
-static void test_strnrchr(void)
-{
-    char *str = "Stringing";
-    size_t len = mm_strlen(str);
-
-    ASSERT(mm_strnrchr(str, 't', len) == &str[1]);
-    ASSERT(mm_strnrchr(str, 'z', len) == NULL);
-    ASSERT(mm_strnrchr(str, 'i', 3) == NULL);
-    ASSERT(*(mm_strnrchr(str, 'i', 4)) == 'i');
-    ASSERT(mm_strnrchr(str, 'S', 0) == NULL);
-    ASSERT(mm_strnrchr(str, 'i', len) == &str[6]);
-}
-
-static void test_strrchr(void)
-{
-    char *str = "String-t";
-
-    ASSERT(mm_strrchr(str, 't') == &str[7]);
-    ASSERT(mm_strrchr(str, 'z') == NULL);
-}
-
-static void test_strspl(void)
-{
-    char str[] = "|These|are||separated|words|";
-    char str2[] = "|These|are||separated|words|";
-    char *cstr[] = {
-       "",
-       "These",
-       "are",
-       "",
-       "separated",
-       "words"
-    };
-    char *cols[7];
-    int v;
-
-    v = mm_strspl(cols, str, 7, '|');
-    ASSERT(v == 6);
-    CMPCOLS(cols, cstr, v);
-
-    v = mm_strspl(cols, str2, 5, '|');
-    ASSERT(v == 5);
-    CMPCOLS(cols, cstr, v);
-}
-
-static void test_strlower(void)
-{
-    char *str = "somemixedcaseword", str2[] = "SomeMixedCaseWord";
-
-    mm_strlower(str2);
-    ASSERT(mm_strcmp(str2, str) == 0);
-}
-
-static void test_strupper(void)
-{
-    char *str = "SOMEMIXEDCASEWORD", str2[] = "SomeMixedCaseWord";
-
-    mm_strupper(str2);
-    ASSERT(mm_strcmp(str2, str) == 0);
-}
-
-static void test_strpack32(void)
-{
-    char *str = "CMD", *str2 = "CMD1";
-    u_int32_t v;
-
-    v = mm_strpack32(str, 3);
-    ASSERT(v == 0x00434d44U);
-
-    v = mm_strpack32(str2, 4);
-    ASSERT(v == 0x434d4431U);
-}
-
-static void test_htol(void)
-{
-    ASSERT(mm_htol("01aBcDeF") == 0x01abcdefU);
-}
-
-static void test_strrev(void)
-{
-    char str[] = "Hello", *str2 = "olleH";
-
-    mm_strrev(str);
-    ASSERT(mm_strcmp(str, str2) == 0);
-}
-
-static void test_strhash64(void)
-{
-    ASSERT(mm_strhash64("This is a test!") == 0x3cafb1cf796f93bcULL);
-}
-
-static void test_memhash64(void)
-{
-    char *str = "This is a test!";
-
-    ASSERT(mm_memhash64(str, mm_strlen(str)) == 0x3cafb1cf796f93bcULL);
-}
-
-static void test_memhash32(void)
-{
-    char *str = "This is a test!";
-
-    ASSERT(mm_memhash32(str, mm_strlen(str)) == 0x34a6c6fcU);
-}
-
-static void test_memcasehash32(void)
-{
-    char *str1 = "This is a test!", *str2 = "THiS Is A TeSt!";
-
-    ASSERT(mm_memcasehash32(str1, mm_strlen(str1)) == 0x8202b2fcU);
-    ASSERT(mm_memcasehash32(str1, mm_strlen(str1)) ==
-               mm_memcasehash32(str2, mm_strlen(str2)));
-}
-
-static void test_memcasecmp(void)
-{
-    ASSERT(mm_memcasecmp("1", "2", 1) == -1);
-    ASSERT(mm_memcasecmp("1", "1", 1) == 0);
-    ASSERT(mm_memcasecmp("2", "1", 1) == 1);
-    ASSERT(mm_memcasecmp("a", "B", 1) == -1);
-    ASSERT(mm_memcasecmp("a", "A", 1) == 0);
-    ASSERT(mm_memcasecmp("b", "A", 1) == 1);
-}
-
-/* To properly test the following, aligned and unaligned memory must be used.
- * We also need to test small and large memory areas. This is because these
- * functions perform optimizations to operate faster on aligned and large
- * areas.
- */
-
-#define BSIZ 4096
-
-static void test_memset(void)
-{
-    char *mem;
-
-    ASSERT((mem = malloc(BSIZ)) != NULL);
-
-    ASSERT(mm_memset(mem, 'x', BSIZ) == mem);
-    CMPBYTES(mem, 'x', BSIZ);
-
-    ASSERT(mm_memset(mem, 'y', 8) == mem);
-    CMPBYTES(mem, 'y', 8);
-
-    ASSERT(mm_memset(mem + 2, 'z', BSIZ - 2) == mem + 2);
-    CMPBYTES(mem + 2, 'z', BSIZ - 2);
-
-    free(mem);
-}
-
-static void test_memcmp(void)
-{
-    char *mem, *mem2;
-
-    ASSERT(mm_memcmp("1", "2", 1) == -1);
-    ASSERT(mm_memcmp("1", "1", 1) == 0);
-    ASSERT(mm_memcmp("2", "1", 1) == 1);
-
-    ASSERT((mem = malloc(BSIZ)) != NULL);
-
-    (void) mm_memset(mem, 'z', BSIZ);
-    mem[BSIZ - 1] = '\0';
-
-    ASSERT((mem2 = _mm_strdup(mem)) != NULL);
-
-    ASSERT(mm_memcmp(mem, mem2, BSIZ) == 0);
-    ASSERT(mm_memcmp(mem + 1, mem2 + 1, BSIZ - 1) == 0);
-    ASSERT(mm_memcmp(mem + 2, mem2 + 2, BSIZ - 2) == 0);
-    ASSERT(mm_memcmp(mem + 3, mem2 + 3, BSIZ - 3) == 0);
-    ASSERT(mm_memcmp(mem + 4, mem2 + 4, BSIZ - 4) == 0);
-
-    mem[BSIZ / 2] = '\0';
-    ASSERT(mm_memcmp(mem, mem2, BSIZ) != 0);
-    ASSERT(mm_memcmp(mem + 1, mem2 + 1, BSIZ - 1) != 0);
-    ASSERT(mm_memcmp(mem + 2, mem2 + 2, BSIZ - 2) != 0);
-    ASSERT(mm_memcmp(mem + 3, mem2 + 3, BSIZ - 3) != 0);
-    ASSERT(mm_memcmp(mem + 4, mem2 + 4, BSIZ - 4) != 0);
-
-    ASSERT(mm_memcmp(mem + 2, mem2, BSIZ - 2) != 0);
-    ASSERT(mm_memcmp(mem + 3, mem2, BSIZ - 3) != 0);
-
-    free(mem2);
-    free(mem);
-}
-
-static void test_memcpy(void)
-{
-    char *mem, *mem2;
-
-    ASSERT((mem = malloc(BSIZ)) != NULL);
-    ASSERT((mem2 = malloc(BSIZ)) != NULL);
-
-    (void) mm_memset(mem, 'x', BSIZ);
-    ASSERT(mm_memcpy(mem2, mem, BSIZ) == mem2);
-    ASSERT(mm_memcmp(mem2, mem, BSIZ) == 0);
-    mem[BSIZ / 2] = '\0';
-    ASSERT(mm_memcmp(mem2, mem, BSIZ) != 0);
-
-    (void) mm_memset(mem, 'y', BSIZ);
-    ASSERT(mm_memcpy(mem2 + 1, mem + 1, BSIZ - 1) == mem2 + 1);
-    ASSERT(mm_memcmp(mem2 + 1, mem + 1, BSIZ - 1) == 0);
-    mem[BSIZ / 2] = '\0';
-    ASSERT(mm_memcmp(mem2 + 1, mem + 1, BSIZ - 1) != 0);
-
-    (void) mm_memset(mem, 'z', BSIZ);
-    ASSERT(mm_memcpy(mem2 + 1, mem, BSIZ - 2) == mem2 + 1);
-    ASSERT(mm_memcmp(mem2 + 1, mem, BSIZ - 2) == 0);
-    mem[BSIZ / 2] = '\0';
-    ASSERT(mm_memcmp(mem2 + 1, mem, BSIZ - 2) != 0);
-
-    free(mem2);
-    free(mem);
-}
-
-#define SSIZ 64
-static void test_memmove(void)
-{
-    char *mem, *mem2;
-
-    ASSERT((mem = malloc(BSIZ)) != NULL);
-    ASSERT((mem2 = malloc(SSIZ)) != NULL);
-
-    {
-       unsigned char *ptr, *toptr, c;
-
-       for (ptr = toptr = mem2, toptr += SSIZ, c = 1; ptr < toptr; ptr++)
-           *ptr = c++;
-    }
-
-    (void) mm_memset(mem, 'x', BSIZ);
-    (void) mm_memcpy(mem + 16, mem2, SSIZ);
-
-    /* Supposed to not do anything */
-    ASSERT(mm_memmove(mem + 16, mem + 16, SSIZ) == mem + 16);
-    ASSERT(mm_memcmp(mem + 16, mem2, SSIZ) == 0);
-
-    /* Word-optimized increasing order move */
-    ASSERT(mm_memmove(mem + 8, mem + 16, SSIZ) == mem + 8);
-    ASSERT(mm_memcmp(mem + 8, mem2, SSIZ) == 0);
-
-    /* Word-optimized decreasing order move */
-    ASSERT(mm_memmove(mem + 16, mem + 8, SSIZ) == mem + 16);
-    ASSERT(mm_memcmp(mem + 16, mem2, SSIZ) == 0);
-
-    /* Increasing order move */
-    ASSERT(mm_memmove(mem + 15, mem + 16, SSIZ) == mem + 15);
-    ASSERT(mm_memcmp(mem + 15, mem2, SSIZ) == 0);
-
-    /* Decreasing order move */
-    ASSERT(mm_memmove(mem + 16, mem + 15, SSIZ) == mem + 16);
-    ASSERT(mm_memcmp(mem + 16, mem2, SSIZ) == 0);
-
-    free(mem2);
-    free(mem);
-}
-#undef SSIZ
-
-#undef BSIZ
diff --git a/site/contributors.html b/site/contributors.html
deleted file mode 100644 (file)
index 42b5895..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-
-<html><head>
-<!--   $Id: contributors.html,v 1.5 2003/06/04 12:17:47 mmondor Exp $
-       Copyright (c) 2002-2003 Matthew Mondor,  ALL RIGHTS RESERVED.
--->
-<title>Matthew Mondor's Software Site - Contributors</title>
-<link rel="shortcut icon" href="/favicon.ico">
-</head>
-
-<!-- Begin -->
-<body bgcolor="#f0f0ff" text="#000000" link="#3535c5" vlink="#700080">
-<table border="0" cellspacing="5" cellpadding="5" width="100%">
-<tbody><tr>
-
-<!-- Left column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Sections</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<p><font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html">Main</a>&nbsp;<br>
-&nbsp;<a href="software.html">Software</a>&nbsp;<br>
-&nbsp;<a href="donations.html">Donations</a>&nbsp;<br>
-&nbsp;<a href="contributors.html"><em>Contributors</em></a>&nbsp;<br>
-&nbsp;<a href="philosophy.html">Philosophy</a>&nbsp;<br>
-&nbsp;<a href="cvs.html">CVS</a>&nbsp;<br>
-&nbsp;<a href="projects.html">Projects</a>&nbsp;<br>
-&nbsp;<a href="mirrors.html">Mirrors</a>&nbsp;<br>
-&nbsp;<a href="mailto:mmondor@gobot.ca">Contact</a>&nbsp;<br>
-</font></td></tr></tbody></table>
-<br><img src="images/sigil.jpg" alt="Image Copyright (c) 2002-2003, Matthew Mondor">
-</td></p>
-
-<!-- Middle column -->
-<td valign="top">
-<center>
-<font face="helvetica, arial" size="4">MMSoftware Contributors</font><br>
-</center>
-<font face="helvetica, arial">
-<p>
-These contributors generally consist of various mmsoftware users across the
-globe who are developing related third-party software, to add features such as
-frontends and configuration tools. They are free to release their software
-under their prefered licenses and conditions. The contributors maintain
-their own software themselves, so bug reports or suggestions should be sent
-directly to them. The content of their section become their own responsibility.
-To obtain sources for the official mmsoftware releases please visit the
-<a href="software.html">software</a> area.
-</p><p>
-I personally thank the contributors for their interest in my projects.
-</p>
-<table border="1" bgcolor="#d0d0f0" width="100%">
-<tr><td align="center">
-<a href="software/contributors/joostendorp/index.html">Jeroen Oostendorp</a>
-</td></tr>
-<tr><td align="center">
-<a href="software/contributors/ddemaggio/index.html">Daniel DeMaggio</a>
-</td></tr>
-<tr><td align="center">
-<a href="software/contributors/aschlett/index.html">Alexander Schlett</a>
-</td></tr>
-<tr><td align="center">
-<a href="software/contributors/jkbentzen/index.html">Jonas Koch Bentzen</a>
-</td></tr>
-<tr><td align="center">
-<a href="software/contributors/vigityan/index.html">Vahram Igityan</a>
-</td></tr>
-</table>
-</font>
-</td>
-
-<!-- Right column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Languages</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html"><em>English</em></a>&nbsp;<br>
-&nbsp;<a href="index_fr.html">French</a>&nbsp;<br>
-</font></td></tr></tbody></table></p>
-<p><font face="helvetica, arial" color="#000066"><b>Mirrors</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="http://mmondor.dynup.net/index.html">Canada</a>&nbsp;<br>
-&nbsp;<a href="http://gobot.accela.net/index.html"><nobr>United-States</nobr></a>&nbsp;<br>
-&nbsp;<a href="http://mmondor.oostendorp-ict.nl/index.html">Holland</a>&nbsp;<br
->
-</font></td></tr></tbody></table></td></p>
-
-<!-- End -->
-</tr><tr><td valign="bottom" align="left" colspan="3">
-<font face="helvetica, arial" size="-2">
-$Id: contributors.html,v 1.5 2003/06/04 12:17:47 mmondor Exp $<br>
-This site Copyright (c) 2002-2003, Matthew Mondor, ALL RIGHTS RESERVED.
-</font></td></tr></tbody></table>
-</body></html>
diff --git a/site/cvs.html b/site/cvs.html
deleted file mode 100644 (file)
index d5f219a..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-
-<html><head>
-<!--   $Id: cvs.html,v 1.7 2003/12/10 20:33:58 mmondor Exp $
-       Copyright (c) 2002-2003 Matthew Mondor,  ALL RIGHTS RESERVED.
--->
-<title>Matthew Mondor's Software Site - CVS</title>
-<link rel="shortcut icon" href="/favicon.ico">
-</head>
-
-<!-- Begin -->
-<body bgcolor="#f0f0ff" text="#000000" link="#3535c5" vlink="#700080">
-<table border="0" cellspacing="5" cellpadding="5" width="100%">
-<tbody><tr>
-
-<!-- Left column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Sections</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<p><font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html">Main</a>&nbsp;<br>
-&nbsp;<a href="software.html">Software</a>&nbsp;<br>
-&nbsp;<a href="donations.html">Donations</a>&nbsp;<br>
-&nbsp;<a href="contributors.html">Contributors</a>&nbsp;<br>
-&nbsp;<a href="philosophy.html">Philosophy</a>&nbsp;<br>
-&nbsp;<a href="cvs.html"><em>CVS</em></a>&nbsp;<br>
-&nbsp;<a href="projects.html">Projects</a>&nbsp;<br>
-&nbsp;<a href="mirrors.html">Mirrors</a>&nbsp;<br>
-&nbsp;<a href="mailto:mmondor@gobot.ca">Contact</a>&nbsp;<br>
-</font></td></tr></tbody></table>
-<br><img src="images/sigil.jpg" alt="Image Copyright (c) 2002-2003, Matthew Mondor">
-</td></p>
-
-<!-- Middle column -->
-<td valign="top">
-<center>
-<font face="helvetica, arial" size="4">MMSoftware CVS Repository</font><br>
-</center>
-<font face="helvetica, arial">
-<p>
-Note that the CVS repository contains the latest actual development tree
-and should not be used by the general public, it is mostly intended for
-developpers, maintainers and beta-testers. There also can be found some
-software which never have previously been released in the form of an archive.
-</p><p>
-The HTTP cvsweb interface to the CVS repository is no longer available at
-present time. However, read-only public CVS pserver access is provided.
-I highly suggest getting aquainted with the command-line cvs(1) utility
-for best results.
-</p><p>
-Those who want to access the repository via public pserver to access all
-of my BSD-style licensed open source software can use the following command:
-</p><p><font face="times" size="-1">
-% cvs -z6 -d:pserver:anoncvs@cvs.accela.net:/cvsroot co mmondor
-</font></p><p>
-To only obtain the Xisop kernel, <em>mmondor/Xisop</em> may be used as the
-module name. To only retreive the mmsoftware directory,
-<em>mmondor/mmsoftware</em> will be used.</p><p>
-The service is provided using the cvs(1), mmspawnd(8) and mmanoncvs(8)
-utilities as an alternative to the common setup using inetd(8). This
-ensures a secure public pserver setup which cannot affect the original
-repositories or the rest of the system if exploited.
-</font>
-</td>
-
-<!-- Right column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Languages</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html"><em>English</em></a>&nbsp;<br>
-&nbsp;<a href="index_fr.html">French</a>&nbsp;<br>
-</font></td></tr></tbody></table></p>
-<p><font face="helvetica, arial" color="#000066"><b>Mirrors</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="http://mmondor.dynup.net/index.html">Canada</a>&nbsp;<br>
-&nbsp;<a href="http://gobot.accela.net/index.html"><nobr>United-States</nobr></a>&nbsp;<br>
-&nbsp;<a href="http://mmondor.oostendorp-ict.nl/index.html">Holland</a>&nbsp;<br
->
-</font></td></tr></tbody></table></td></p>
-
-<!-- End -->
-</tr><tr><td valign="bottom" align="left" colspan="3">
-<font face="helvetica, arial" size="-2">
-$Id: cvs.html,v 1.7 2003/12/10 20:33:58 mmondor Exp $<br>
-This site Copyright (c) 2002-2003, Matthew Mondor, ALL RIGHTS RESERVED.
-</font></td></tr></tbody></table>
-</body></html>
diff --git a/site/donations.html b/site/donations.html
deleted file mode 100644 (file)
index d57d2f1..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-
-<html><head>
-<!--   $Id: donations.html,v 1.6 2003/06/04 12:17:47 mmondor Exp $
-       Copyright (c) 2002-2003 Matthew Mondor,  ALL RIGHTS RESERVED.
--->
-<title>Matthew Mondor's Software Site - Donations</title>
-<link rel="shortcut icon" href="/favicon.ico">
-</head>
-
-<!-- Begin -->
-<body bgcolor="#f0f0ff" text="#000000" link="#3535c5" vlink="#700080">
-<table border="0" cellspacing="5" cellpadding="5" width="100%">
-<tbody><tr>
-
-<!-- Left column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Sections</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<p><font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html">Main</a>&nbsp;<br>
-&nbsp;<a href="software.html">Software</a>&nbsp;<br>
-&nbsp;<a href="donations.html"><em>Donations</em></a>&nbsp;<br>
-&nbsp;<a href="contributors.html">Contributors</a>&nbsp;<br>
-&nbsp;<a href="philosophy.html">Philosophy</a>&nbsp;<br>
-&nbsp;<a href="cvs.html">CVS</a>&nbsp;<br>
-&nbsp;<a href="projects.html">Projects</a>&nbsp;<br>
-&nbsp;<a href="mirrors.html">Mirrors</a>&nbsp;<br>
-&nbsp;<a href="mailto:mmondor@gobot.ca">Contact</a>&nbsp;<br>
-</font></td></tr></tbody></table>
-<br><img src="images/sigil.jpg" alt="Image Copyright (c) 2002-2003, Matthew Mondor">
-</td></p>
-
-<!-- Middle column -->
-<td valign="top">
-<center>
-<font face="helvetica, arial" size="4">Donations to support MMSoftware</font><br>
-</center>
-<font face="helvetica, arial">
-<p>
-Free opensource software projects need the support of their users to evolve.
-Programmers spend alot of time trying to make the code efficient, bug-free,
-and user-friendly. In an area where security is a primary concern, like for
-public internet services, the time required to roll safe code is often higher
-than it would be for some other projects. There are design, coding, testing,
-debugging, and auditing sessions. And at times even restructuring when
-required to allow the software to be more manageable for the forthcoming new
-features it should integrate.
-</p><p>
-There are many ways one can use to support the project. One is to help it
-maintain public exposure by providing hosting and bandwidth for a mirror.
-This obviously only should be done on stable connections, it can then become
-useful for people to find a mirror closer to their location, and so that at
-all times at least one mirror remains up if others are ever temporarily down.
-The mmondor.gobot.ca DNS pool of addresses can then be updated once a day,
-verifying the availability and stability of the mirrors. An FTP account or
-other method can be used to mirror the site regularly.
-</p><p>
-Another way is to audit the software against potential security, portability
-issues and bugs, as well as test the software. Beta testers are welcome to
-track the CVS repository tree and to propose diff/patches whenever necessary.
-Also considered a donation is the time other programmers can put in
-contributing third party software related to the projects. Although this may
-not necessarily affect mmsoftware directly, some of that software may be very
-useful for many mmsoftware users.
-</p><p>
-It is also possible to sponsor the work on a particular opensource project or
-feature of one of the existing project by material and/or money donations.
-For example, one may want the software to support another UNIX-style system
-for which the software does not currently work for some reason, and provide
-the necessary hardware and/or software tools to allow to do it.
-</p><p>
-As we are mostly dealing with BSD licensed software it is also possible to
-hire us in order to develop a closed-source implementation with
-custom-specific needs of one of the existing projects. The customer would
-decide whether or not the new branch should eventually be donated, back to the
-main public repository, to fall back under the same BSD-license as well
-(possibly with an advertising clause in the license text).
-</p><p>
-Finally, a thing which is always encouraging and doesn't cost much, is to
-send positive feedback, via email or on freshmeat, about the features you
-enjoy in mmsoftware, if you decide to use it. Gifts are also welcome.
-</p><p>
-We appreciate your contribution to our common goal. We would like to assure
-you that we use it to the best of our efforts to help the project evolve.
-</p><p><font size="-1">
-Matthew Mondor
-</p>
-</font>
-</td>
-
-<!-- Right column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Languages</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html"><em>English</em></a>&nbsp;<br>
-&nbsp;<a href="index_fr.html">French</a>&nbsp;<br>
-</font></td></tr></tbody></table></p>
-<p><font face="helvetica, arial" color="#000066"><b>Mirrors</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="http://mmondor.dynup.net/index.html">Canada</a>&nbsp;<br>
-&nbsp;<a href="http://gobot.accela.net/index.html"><nobr>United-States</nobr></a>&nbsp;<br>
-&nbsp;<a href="http://mmondor.oostendorp-ict.nl/index.html">Holland</a>&nbsp;<br
->
-</font></td></tr></tbody></table></td></p>
-
-<!-- End -->
-</tr><tr><td valign="bottom" align="left" colspan="3">
-<font face="helvetica, arial" size="-2">
-$Id: donations.html,v 1.6 2003/06/04 12:17:47 mmondor Exp $<br>
-This site Copyright (c) 2002-2003, Matthew Mondor, ALL RIGHTS RESERVED.
-</font></td></tr></tbody></table>
-</body></html>
diff --git a/site/favicon.ico b/site/favicon.ico
deleted file mode 100644 (file)
index dcac835..0000000
Binary files a/site/favicon.ico and /dev/null differ
diff --git a/site/images/CVS.jpg b/site/images/CVS.jpg
deleted file mode 100644 (file)
index 4e382fc..0000000
Binary files a/site/images/CVS.jpg and /dev/null differ
diff --git a/site/images/key.jpg b/site/images/key.jpg
deleted file mode 100644 (file)
index 6b3f9df..0000000
Binary files a/site/images/key.jpg and /dev/null differ
diff --git a/site/images/sigil.jpg b/site/images/sigil.jpg
deleted file mode 100644 (file)
index d6f6ace..0000000
Binary files a/site/images/sigil.jpg and /dev/null differ
diff --git a/site/index.html b/site/index.html
deleted file mode 100644 (file)
index 25f857c..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-
-<html><head>
-<!--   $Id: index.html,v 1.9 2003/09/30 05:34:53 mmondor Exp $
-       Copyright (c) 2002-2003 Matthew Mondor,  ALL RIGHTS RESERVED.
--->
-<title>Matthew Mondor's Software Site - Main</title>
-<link rel="shortcut icon" href="/favicon.ico">
-</head>
-
-<!-- Begin -->
-<body bgcolor="#f0f0ff" text="#000000" link="#3535c5" vlink="#700080">
-<table border="0" cellspacing="5" cellpadding="5" width="100%">
-<tbody><tr>
-
-<!-- Left column -->
-<p><td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Sections</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html"><em>Main</em></a>&nbsp;<br>
-&nbsp;<a href="software.html">Software</a>&nbsp;<br>
-&nbsp;<a href="donations.html">Donations</a>&nbsp;<br>
-&nbsp;<a href="contributors.html">Contributors</a>&nbsp;<br>
-&nbsp;<a href="philosophy.html">Philosophy</a>&nbsp;<br>
-&nbsp;<a href="cvs.html">CVS</a>&nbsp;<br>
-&nbsp;<a href="projects.html">Projects</a>&nbsp;<br>
-&nbsp;<a href="mirrors.html">Mirrors</a>&nbsp;<br>
-&nbsp;<a href="mailto:mmondor@gobot.ca">Contact</a>&nbsp;<br>
-</font></td></tr></tbody></table>
-<br><img src="images/sigil.jpg" alt="Image Copyright (c) 2002-2003, Matthew Mondor">
-</td></p>
-
-<!-- Middle column -->
-<td valign="top">
-<center>
-<font face="helvetica, arial" size="5">The MMSoftware Project</font><br>
-<a href="http://mmondor.gobot.ca">
-<img border="0" src="images/key.jpg" alt="Image Copyright (c) 2002-2003, Matthew Mondor">
-</a>
-</center>
-<font face="helvetica, arial">
-<p>
-<b>NOTE:</b> The french version is not yet available. Additionally, only
-the master site currently works, mirrors should be up soon.
-</p><p>
-This site provides various opensource <a href="software.html">software</a>
-to anyone who find it useful. The projects mostly were written from scratch by
-Matthew Mondor and released under a BSD-style license, but we also host
-third-party software related to these projects, provided by other
-<a href="contributors.html">contributors</a> worldwide who wanted to make
-their related work freely available.
-</p><p>
-The hosting and bandwidth for the <a href="mirrors.html">mirrors</a> is
-provided by various <a href="donations.html">donators</a> accross the globe.
-Although we attempt to encourage contributors and donators, we try to keep
-this site as free from commercial ads as possible as a convenience to our
-users. The main mmsoftware project <a href="philosophy.html">philosophy</a>
-will describe our goals with more details.
-</p><p>
-Matthew Mondor can be contacted via email at
-<a href="mailto:mmondor@gobot.ca">mmondor@gobot.ca</a> for suggestions,
-contributions, donations, flames, thanks, business and bug reports.
-</p>
-</font>
-</td>
-
-<!-- Right column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Languages</b></font><br>
-<p><table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html"><em>English</em></a>&nbsp;<br>
-&nbsp;<a href="index_fr.html">French</a>&nbsp;<br>
-</font></td></tr></tbody></table></p>
-<p><font face="helvetica, arial" color="#000066"><b>Mirrors</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="http://mmondor.dynup.net/index.html">Canada</a>&nbsp;<br>
-&nbsp;<a href="http://gobot.accela.net/index.html"><nobr>United-States</nobr></a>&nbsp;<br>
-&nbsp;<a href="http://mmondor.oostendorp-ict.nl/index.html">Holland</a>&nbsp;<br
->
-</font></td></tr></tbody></table></td>
-
-<!-- End -->
-</tr><tr><td valign="bottom" align="left" colspan="3">
-<font face="helvetica, arial" size="-2">
-$Id: index.html,v 1.9 2003/09/30 05:34:53 mmondor Exp $<br>
-This site Copyright (c) 2002-2003, Matthew Mondor, ALL RIGHTS RESERVED.
-</font></td></tr></tbody></table>
-</body></html>
diff --git a/site/mirrors.html b/site/mirrors.html
deleted file mode 100644 (file)
index ec0583f..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-
-<html><head>
-<!--   $Id: mirrors.html,v 1.5 2003/06/04 12:17:47 mmondor Exp $
-       Copyright (c) 2002-2003 Matthew Mondor,  ALL RIGHTS RESERVED.
--->
-<title>Matthew Mondor's Software Site - Mirrors</title>
-<link rel="shortcut icon" href="/favicon.ico">
-</head>
-
-<!-- Begin -->
-<body bgcolor="#f0f0ff" text="#000000" link="#3535c5" vlink="#700080">
-<table border="0" cellspacing="5" cellpadding="5" width="100%">
-<tbody><tr>
-
-<!-- Left column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Sections</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<p><font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html">Main</a>&nbsp;<br>
-&nbsp;<a href="software.html">Software</a>&nbsp;<br>
-&nbsp;<a href="donations.html">Donations</a>&nbsp;<br>
-&nbsp;<a href="contributors.html">Contributors</a>&nbsp;<br>
-&nbsp;<a href="philosophy.html">Philosophy</a>&nbsp;<br>
-&nbsp;<a href="cvs.html">CVS</a>&nbsp;<br>
-&nbsp;<a href="projects.html">Projects</a>&nbsp;<br>
-&nbsp;<a href="mirrors.html"><em>Mirrors</em></a>&nbsp;<br>
-&nbsp;<a href="mailto:mmondor@gobot.ca">Contact</a>&nbsp;<br>
-</font></td></tr></tbody></table>
-<br><img src="images/sigil.jpg" alt="Image Copyright (c) 2002-2003, Matthew Mondor">
-</td></p>
-
-<!-- Middle column -->
-<td valign="top">
-<center>
-<font face="helvetica, arial" size="4">MMSoftware Mirrors</font><br>
-</center>
-<font face="helvetica, arial">
-<p>
-Here are the current site mirrors and their generous providers, appearing
-in setup chronological order (first setup to last):
-</p>
-<table border="1" bgcolor="#d0d0f0" width="100%">
-<tr><th>Location</th><th>Provider</th><th>URL</th></tr>
-<tr>
-<td align="center">United-States</td>
-<td align="center">Matthew J Backes</td>
-<td align="center"><font size="-1"><a href="http://gobot.accela.net">http://gobot.accela.net</a></font></td>
-</tr><tr>
-<td align="center">Holland</td>
-<td align="center">Jeroen Oostendorp</td>
-<td align="center"><font size="-1"><a href="http://mmondor.oostendorp-ict.nl">http://mmondor.oostendorp-ict.nl</a></font></td>
-</tr><tr>
-<td align="center">Canada</td>
-<td align="center">Ryan Werber</td>
-<td align="center"><font size="-1"><a href="http://mmondor.dynup.net">http://mmondor.dynup.net</a></font></td>
-</tr>
-</table>
-<p>
-If you would like to provide hosting space and bandwidth for a new mirror,
-this would consist of a service donation, please consult the
-<a href="donations.html">donations</a> area for more information about the
-requirements and suggestions.
-</p>
-</font>
-</td>
-
-<!-- Right column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Languages</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html"><em>English</em></a>&nbsp;<br>
-&nbsp;<a href="index_fr.html">French</a>&nbsp;<br>
-</font></td></tr></tbody></table></p>
-<p><font face="helvetica, arial" color="#000066"><b>Mirrors</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="http://mmondor.dynup.net/index.html">Canada</a>&nbsp;<br>
-&nbsp;<a href="http://gobot.accela.net/index.html"><nobr>United-States</nobr></a>&nbsp;<br>
-&nbsp;<a href="http://mmondor.oostendorp-ict.nl/index.html">Holland</a>&nbsp;<br
->
-</font></td></tr></tbody></table></td></p>
-
-<!-- End -->
-</tr><tr><td valign="bottom" align="left" colspan="3">
-<font face="helvetica, arial" size="-2">
-$Id: mirrors.html,v 1.5 2003/06/04 12:17:47 mmondor Exp $<br>
-This site Copyright (c) 2002-2003, Matthew Mondor, ALL RIGHTS RESERVED.
-</font></td></tr></tbody></table>
-</body></html>
diff --git a/site/new/TODO b/site/new/TODO
deleted file mode 100644 (file)
index 9a13720..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-Because there is a general layout already for the site (left column with
-a main menu, center column with the content for the current page and
-right column for the language menu), I should design something which uses
-templates or such. I did so for the spes project a while back, but which
-dynamically generated the pages, using php.
-
-I want something with which I can simply type a make command for it to
-generate the static html pages. There would be a list of languages and
-for each the process would be automatically repeated, also. For each
-language, a left main menu and right language selection menu would be
-generated, and it's center column contents generated from a template.
-Example of a possible layout:
-
-build/
-build/lang/english
-build/lang/english/menu_main.txt
-build/lang/english/menu_lang.txt
-build/lang/english/page_index.txt
-build/lang/english/page_cvs.txt
-build/lang/english/page_software.txt
-build/lang/english/page_philosophy.txt
-build/lang/english/soft_descriptions.txt
-build/soft_releases.txt
-build/languages.txt
-htdocs/
-
-The files would be generated into htdocs/
-The soft_descriptions.txt file would hold a map of software name->short
-description -> long description, to be used by build/soft_releases.txt in
-lang/page_software.txt .
-build/languages would hold a list of available languages.
-
-The format of the manu_*.txt files would be as follows:
-
-"<Menu title>
-"<Filename>" "<Menu description>"
-
-I.E.
-
-"Sections"
-"index"                "Main"
-"software"     "Software"
-"donations"    "Donations"
-"contributors" "Contributors"
-"philosophy"   "Philosophy"
-"cvs"          "CVS"
-"projects"     "Projects"
-"mirrors"      "Mirrors"
-"contact"      "Contact"
-
-The filename will be suffixed with the language suffix in the htdocs/
-directory, and the file will be generated from the language/page_<filename>.txt
-file.
-
-The format of the languages.txt file would be as follows:
-
-<Suffix> <Directory>
-
-I.E.
-
-en english
-fr french
-ru russian
-
-The format of the page_*.txt files would be standard HTML, but which could
-contain special keywords. The only current special keyword consists of:
-.soft releases
-which should be beginning at the first column, as-is, on a single line.
-This keyword causes the soft_releases.txt file to be parsed with the
-language/soft_descriptions.txt, to create a table of all the available
-software.
-It is possible to do:
-.soft maintained
-.soft unmaintained
-etc.
-
-I also need a special command for mirrors table. And one for links.
-The one for links would automatically append the language suffix and
-html extension...
-
-.link <name> <show>
-.mirrors
-
-A similar system for FAQs:
-
-.faq <name>
-
-
-TODO
-====
-
-- Verify apache multilingual support to use the same convention for
-  page storage...
diff --git a/site/new/build/GNUmakefile b/site/new/build/GNUmakefile
deleted file mode 100644 (file)
index f04011d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# $Id: GNUmakefile,v 1.1 2004/04/30 00:05:53 mmondor Exp $
-
-MMLIBS := $(addprefix ../../../mmsoftware/mmlib/,mmpool.o mmlog.o \
-mmreadcfg.o mmstring.o mmhash.o)
-
-OBJS := mmsite.o
-
-CFLAGS += -Wall -DDEBUG
-
-
-all: mmsite
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I../../../mmsoftware/mmlib -o $@ $<
-
-mmsite: $(MMLIBS) $(OBJS)
-       cc -o $@ $(OBJS) -lc $(MMLIBS)
-
-clean:
-       rm -f mmsite $(OBJS) $(MMLIBS)
diff --git a/site/new/build/README b/site/new/build/README
deleted file mode 100644 (file)
index dc99aeb..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-It was chosen to use a simple system based on text files which could be
-used with CVS rather than another type of database to build the site's
-HTML files from. This allows contributors to simply send a diff generated
-by CVS containing their update suggestions and additions. Also, generating
-a static site has advantages, allowing cacheing for efficiency by HTTP
-cache proxies, and easing the task of mirrors updating their copy of the site.
-
-This system makes it easy to maintain the list of available software, as
-well as to translate the site to other languages, while avoiding HTML
-formatting and linking bugs. It also enforces the site's general layout
-through all the site pages. The generated pages are made from an W3C validated
-template for HTML 4.0 Transitional.
-
-The default language causes the pages to have no special suffix, while
-the others will have the short description of the language appended before
-the '.html' extension.
diff --git a/site/new/build/TODO b/site/new/build/TODO
deleted file mode 100644 (file)
index 0832775..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-- Although it is nice to have a few hash tables for fast lookup, some
-  files need to be considered as sequencial lists and will be have to
-  be processed accordingly (using a hash table causes the entries to
-  become in an arbitrary order). Actually, most or all of the base files
-  are lists, while language-specific ones are tables for fast lookup
-  when mapping.
-
-- Work out a system for FAQs similar to the one for software.
-
-- Work out a system for news. This would be nice to announce releases etc
diff --git a/site/new/build/english/faq_mmftpd.txt b/site/new/build/english/faq_mmftpd.txt
deleted file mode 100644 (file)
index 886f552..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-# First line consists of FAQ .title
-# Then following are .section <num> <title> for a section,
-# .question <num> <title> for a question. Each can be followed by
-# arbitrary HTML, and an index will be automatically generated.
-#
-.title "Frequently asked questions about mmftpd"
-This FAQ deals with most common problems which first time users encounter.
-.section "Installation"
-This section deals exclusively with mmftpd installation.
-.question "How do I compile mmftpd?"
-Answer to the question
-.question "Another question?"
-Another answer.
-.section "Configuration"
-This section deals with mmftpd configuration.
-.question "Blah??"
-Answer!?
diff --git a/site/new/build/english/faq_mmmail.txt b/site/new/build/english/faq_mmmail.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/site/new/build/english/faq_mmstatd.txt b/site/new/build/english/faq_mmstatd.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/site/new/build/english/menu_languages.txt b/site/new/build/english/menu_languages.txt
deleted file mode 100644 (file)
index b7033ae..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# One line per entry, two columns:
-# <language> <description>
-#
-MENU   Languages
-english        English
-french French
diff --git a/site/new/build/english/menu_main.txt b/site/new/build/english/menu_main.txt
deleted file mode 100644 (file)
index ad38d2a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-MENU           Sections
-index          Main
-software       Software
-donations      Donations
-contributors   Contributors
-philosophy     Philosophy
-cvs            CVS
-projects       Projects
-mirrors                Mirrors
-contact                Contact
diff --git a/site/new/build/english/menu_mirrors.txt b/site/new/build/english/menu_mirrors.txt
deleted file mode 100644 (file)
index 6ef947b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# One line per entry, two columns:
-# <name> <description>
-#
-MENU           Mirrors
-canada         Canada
-united-states  United-States
-holland                Holland
diff --git a/site/new/build/english/page_contact.txt b/site/new/build/english/page_contact.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/site/new/build/english/page_contributors.txt b/site/new/build/english/page_contributors.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/site/new/build/english/page_cvs.txt b/site/new/build/english/page_cvs.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/site/new/build/english/page_donations.txt b/site/new/build/english/page_donations.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/site/new/build/english/page_index.txt b/site/new/build/english/page_index.txt
deleted file mode 100644 (file)
index 5604f94..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<p><b>NOTE:</b> The French version of this site is not yet available.
-Additionally, only the master site currently works, mirrors should
-be back up eventually.</p>
-<p>This site provides various open source
-.link software software
-to anyone who finds it useful. The projects mostly were written from
-scratch by Matthew Mondor and released under a BSD-style license,
-but we also host third-party software related to these projects,
-provided by other
-.link contributors contributors
-worldwide who wanted to make their related work freely available.</p>
-<p>The hosting and bandwidth for the
-.link mirrors mirrors
-is provided by various
-.link donations donators
-accross the globe. Although we attempt to encourage contributors and
-donators, we try to keep this site as free from commercial ads as
-possible as a convenience to our users. The main mmsoftware project
-.links philosophy philosophy will describe our goals with more details.</p>
-<p>Matthew Mondor can be contacted via email at
-<a href="mailto:mmondor@accela.net">mmondor@accela.net</a> for suggestions,
-contributions, donations, flames, thanks, business and bug reports.</p>
diff --git a/site/new/build/english/page_mirrors.txt b/site/new/build/english/page_mirrors.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/site/new/build/english/page_philosophy.txt b/site/new/build/english/page_philosophy.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/site/new/build/english/page_projects.txt b/site/new/build/english/page_projects.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/site/new/build/english/page_software.txt b/site/new/build/english/page_software.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/site/new/build/english/soft_descriptions.txt b/site/new/build/english/soft_descriptions.txt
deleted file mode 100644 (file)
index 3c2bc21..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# Each project is separated by an empty line. The first line of a project
-# consists of it's name, the second line of it's short description, and
-# the following lines, in HTML format, of the long description, ending
-# with an empty line.
-#
-mmftpd
-Unprivileged virtual users FTP server
-Long multiline description follows in HTML, until empty line.
-So it continues...
-And still...
-
-ginseng-ftpd
-blah
-blah
-
diff --git a/site/new/build/mmsite.c b/site/new/build/mmsite.c
deleted file mode 100644 (file)
index 2ef1395..0000000
+++ /dev/null
@@ -1,557 +0,0 @@
-/* $Id: mmsite.c,v 1.1 2004/04/30 00:05:53 mmondor Exp $ */
-
-/*
- * Copyright (C) 2003, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* This program builds the site in htdocs/. Please read mmsite.8 for more
- * information on the required layout. This is a helper to generate correct
- * HTML, translate the site into multiple languages and build the software
- * and faq indexes and tables, using static pages only. This then allows
- * acceleration using cacheing HTTP proxies and helps to more easily provide
- * a straightforward method for mirror providers.
- */
-
-
-
-/* HEADERS */
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <mmtypes.h>
-#include <mmstring.h>
-#include <mmpool.h>
-#include <mmlist.h>
-#include <mmhash.h>
-
-
-
-/* DEFINITIONS */
-
-/* The following system allows to load arbitrary tables from files. The
- * table field is only used for language map to the project descriptions.
- */
-#define COLS_MAX       4
-#define LINE_MAX       256
-
-typedef struct table_node {
-    hashnode_t node;
-    char line[LINE_MAX];
-    char *columns[COLS_MAX];
-    size_t lengths[COLS_MAX];
-    hashtable_t *table;
-} table_node;
-
-/* And for linked lists, where order is necessary */
-typedef struct list_node {
-    node_t node;
-    char line[LINE_MAX];
-    char *columns[COLS_MAX];
-    size_t lengths[COLS_MAX];
-    u_int32_t hash;
-} list_node;
-
-/* The following are definitions helping to use each of our known tables.
- * Let's start with the global ones:
- * --------------------------------
- */
-
-/* table_languages */
-enum columns_languages {
-    LANGUAGES_NAME = 0,
-    LANGUAGES_MAX
-};
-#define LANGUAGES_KEY  LANGUAGES_NAME
-
-/* table_mirrors */
-enum columns_mirrors {
-    MIRRORS_NAME = 0,
-    MIRRORS_URL,
-    MIRRORS_CONTRIBUTOR,
-    MIRRORS_MAX
-};
-#define MIRRORS_KEY    MIRRORS_URL
-
-/* table_pages */
-enum columns_pages {
-    PAGES_NAME = 0,
-    PAGES_MAX
-};
-#define PAGES_KEY      PAGES_NAME
-
-/* table_software */
-enum columns_software {
-    SOFTWARE_CATEGORY = 0,
-    SOFTWARE_DIRECTORY,
-    SOFTWARE_MAX
-};
-#define SOFTWARE_KEY   SOFTWARE_CATEGORY
-
-/* For each of table_software, projects */
-enum columns_projects {
-    PROJECTS_NAME = 0,
-    PROJECTS_STATUS,
-    PROJECTS_VERSION,
-    PROJECTS_MAX
-};
-#define PROJECTS_KEY   PROJECTS_NAME
-
-/* Following are the language-specific tables:
- * ------------------------------------------
- */
-
-/* table_menu_languages */
-enum columns_menu_languages {
-    MENU_LANGUAGES_NAME = 0,
-    MENU_LANGUAGES_DESCR
-};
-
-#define MENU_LANGUAGES_KEY     MENU_LANGUAGES_NAME
-
-/* This structure is hold to hold nodes in project description tables */
-
-#define TDN_PROJECT_MAX        32
-#define TDN_DESCR_S_MAX        256
-#define TDN_DESCR_L_MAX        2048
-
-typedef struct table_descr_node {
-    hashnode_t node;
-    char project[TDN_PROJECT_MAX];
-    char descr_s[TDN_DESCR_S_MAX];
-    char descr_l[TDN_DESCR_L_MAX];
-} table_descr_node;
-
-
-
-/* PROTOTYPES */
-
-int main(void);
-
-static hashtable_t *table_load(const char *, unsigned int, unsigned int);
-static hashtable_t *table_descr_load(const char *);
-static hashtable_t *table_free(hashtable_t *);
-static list_t *list_load(const char *, unsigned int, unsigned int);
-static list_t *list_free(list_t *);
-
-
-
-/* GLOBALS */
-
-static pool_t table_pool, table_descr_pool, list_pool;
-static hashtable_t *table_languages = NULL, *table_descriptions = NULL;
-
-static list_t *list_software = NULL;
-
-
-
-/* CODE */
-
-int main(void)
-{
-    /* First initialize our fast memory management pools */
-    if (!pool_init(&table_pool, malloc, free, sizeof(table_node),
-               65536 / sizeof(table_node), 0, 0)) {
-       (void) fprintf(stderr, "main() - pool_init(table_pool)\n");
-       return EXIT_FAILURE;
-    }
-    if (!pool_init(&table_descr_pool, malloc, free, sizeof(table_descr_node),
-               65536 / sizeof(table_descr_node), 0, 0)) {
-       (void) fprintf(stderr, "main() - pool_init(table_descr_pool)\n");
-       return EXIT_FAILURE;
-    }
-    if (!pool_init(&list_pool, malloc, free, sizeof(list_node),
-               65536 / sizeof(list_node), 0, 0)) {
-       (void) fprintf(stderr, "main() - pool_init(list_pool)\n");
-       return EXIT_FAILURE;
-    }
-
-    /* Load global lists */
-    if ((list_languages = list_load("site_languages.txt", LANGUAGES_MAX,
-                   LANGUAGES_KEY)) == NULL) {
-       (void) fprintf(stderr, "main() - list_load(site_languages.txt)\n");
-       return EXIT_FAILURE;
-    }
-    if ((list_mirrors = list_load("site_mirrors.txt", MIRRORS_MAX,
-                   MIRRORS_KEY)) == NULL) {
-       (void) fprintf(stderr, "main() - list_load(site_mirrors.txt)\n");
-       return EXIT_FAILURE;
-    }
-
-    /* Load required lists */
-    if ((table_languages = table_load("site_languages.txt", LANGUAGES_MAX,
-                   LANGUAGES_KEY)) == NULL) {
-       (void) fprintf(stderr, "main() - table_load(languages)\n");
-       return EXIT_FAILURE;
-    }
-    if ((table_descriptions = table_descr_load(
-                   "english/soft_descriptions.txt")) == NULL) {
-       (void) fprintf(stderr, "main() - table_descr_load(descriptions)\n");
-       return EXIT_FAILURE;
-    }
-    if ((list_software = list_load("site_software.txt", SOFTWARE_MAX,
-                   SOFTWARE_KEY)) == NULL) {
-       (void) fprintf(stderr, "main() - list_load(software)\n");
-       return EXIT_FAILURE;
-    } else {
-       list_node *node;
-
-       for (node = DLIST_TOP(list_software); node != NULL;
-               node = DLIST_NEXT(node))
-           (void) printf("'%s|%s'\n", node->columns[SOFTWARE_CATEGORY],
-                         node->columns[SOFTWARE_DIRECTORY]);
-    }
-
-    {
-       table_node *node;
-
-       if ((node = (table_node *)hashtable_lookup(table_languages,
-                       "english", 7))
-               != NULL)
-           (void) printf("%s\n", node->columns[LANGUAGES_NAME]);
-       else
-           (void) printf("'english' not found!\n");
-    }
-    {
-       table_descr_node *node;
-
-       if ((node = (table_descr_node *)hashtable_lookup(table_descriptions,
-                       "mmftpd", 6)) != NULL) {
-           (void) printf("Project: %s\n", node->project);
-           (void) printf("Descr_s: %s\n", node->descr_s);
-           (void) printf("Descr_l: %s", node->descr_l);
-       } else
-           (void) printf("'mmftpd' not found!\n");
-    }
-
-    table_languages = table_free(table_languages);
-    return EXIT_SUCCESS;
-}
-
-
-/* Loads a hash table from the specified text file which holds one entry
- * per line and <cols> expected columns each. Links each entry to the table
- * using <key> column as the lookup key. Returns the hashtable_t pointer on
- * success, or NULL.
- */
-static hashtable_t *table_load(const char *file, unsigned int cols,
-       unsigned int key)
-{
-    hashtable_t *table = NULL;
-    table_node *node = NULL;
-    FILE *fh;
-
-    if (cols >= COLS_MAX || key >= COLS_MAX) {
-       (void) fprintf(stderr, "table_load(%s) - cols|key >= COLS_MAX!\n",
-                      file);
-       return NULL;
-    }
-
-    if ((fh = fopen(file, "r")) != NULL) {
-       if ((table = malloc(sizeof(hashtable_t))) != NULL) {
-           if (hashtable_init(table, HT_DEFAULT_CAPACITY, HT_DEFAULT_FACTOR,
-                       malloc, free, mm_memcmp, hashtable_hash, TRUE)) {
-               for (;;) {
-                   int i;
-                   size_t len;
-
-                   if (node == NULL && (node = (table_node *)pool_alloc(
-                                   &table_pool, FALSE)) == NULL) {
-                       (void) fprintf(stderr,
-                                      "table_load(%s) - pool_alloc()\n",
-                                      file);
-                       break;
-                   }
-                   if (fgets(node->line, LINE_MAX - 1, fh) == NULL) {
-                       node = (table_node *)pool_free((pnode_t *)node);
-                       break;
-                   }
-                   len = mm_strlen(node->line);
-                   if (len > 0 && node->line[len - 1] == '\n')
-                       len--;
-                   if (len > 0 && node->line[len - 1] == '\r')
-                       len--;
-                   node->line[len] = '\0';
-                   if (*node->line == '#' || *node->line == '\0')
-                       continue;
-                   if (mm_strasplq(node->columns, node->line, cols) != cols) {
-                       (void) fprintf(stderr,
-                                      "table_load(%s) - Invalid line '%s'\n",
-                                      file, node->line);
-                       break;
-                   }
-                   for (i = 0; i < cols; i++)
-                       node->lengths[i] = mm_strlen(node->columns[i]);
-                   node->table = NULL;
-                   if (!hashtable_link(table, (hashnode_t *)node,
-                               node->columns[key], node->lengths[key])) {
-                       (void) fprintf(stderr,
-                                      "table_load(%s) - link key '%s'\n",
-                                      file, node->columns[key]);
-                       break;
-                   }
-                   node = NULL;
-               }
-               if (node != NULL)
-                   table = table_free(table);
-           } else {
-               (void) fprintf(stderr, "table_load(%s) - hashtable_init()\n",
-                              file);
-               free(table);
-               table = NULL;
-           }
-       } else
-           (void) fprintf(stderr, "table_load(%s) - malloc(table)\n",
-                          file);
-       (void) fclose(fh);
-    }
-
-    return table;
-}
-
-/* This function loads another type of file-based table. For each entry,
- * the first line consists of the project name, the second of the short
- * project description, and the following lines of the long description
- * with allowed embedded HTML for emphasis, ending with an empty line.
- */
-static hashtable_t *table_descr_load(const char *file)
-{
-    hashtable_t *table = NULL;
-    table_descr_node *node = NULL;
-    FILE *fh;
-    char line[TDN_DESCR_S_MAX];
-
-    if ((fh = fopen(file, "r")) != NULL) {
-       if ((table = malloc(sizeof(hashtable_t))) != NULL) {
-           if (hashtable_init(table, HT_DEFAULT_CAPACITY, HT_DEFAULT_FACTOR,
-                       malloc, free, mm_memcmp, hashtable_hash, TRUE)) {
-               int field = 0;
-               size_t descr_l_len = 0, project_len = 0;
-
-               for (;;) {
-                   size_t len;
-
-                   if (node == NULL) {
-                       if ((node = (table_descr_node *)pool_alloc(
-                                       &table_descr_pool, FALSE)) == NULL) {
-                           (void) fprintf(stderr,
-                                      "table_descr_load(%s) - pool_alloc()\n",
-                                      file);
-                           break;
-                       }
-                       /* New entry */
-                       field = 0;
-                       descr_l_len = project_len = 0;
-                   }
-                   if (fgets(line, TDN_DESCR_S_MAX - 1, fh) == NULL) {
-                       if (field == 0)
-                           node = (table_descr_node *)pool_free(
-                                   (pnode_t *)node);
-                       else
-                           (void) fprintf(stderr, "table_descr_load(%s) - \
-Incomplete entry for '%s'\n", file, node->project);
-                       break;
-                   }
-                   len = mm_strlen(line);
-                   if (len > 0 && line[len - 1] == '\n')
-                       len--;
-                   if (len > 0 && line[len - 1] == '\r')
-                       len--;
-                   line[len] = '\0';
-                   if (*line == '#' && field == 0)
-                       continue;
-                   if (len == 0) {
-                       /* Empty line, ignore if between two entries,
-                        * consider it as entry termination if we filled
-                        * them all, generate an error otherwise.
-                        */
-                       if (field == 0)
-                           continue;
-                       else if (field == 2) {
-                           /* Link entry and force new entry creation */
-                           if (!hashtable_link(table, (hashnode_t *)node,
-                                       node->project, project_len)) {
-                               (void) fprintf(stderr, "table_descr_load(%s) \
-- hashtable_link(%s)\n", file, node->project);
-                               break;
-                           }
-                           node = NULL;
-                           continue;
-                       } else {
-                           (void) fprintf(stderr, "table_descr_load(%s) - \
-Incomplete entry for '%s'\n", file, node->project);
-                           break;
-                       }
-                   }
-                   if (field == 0) {
-                       /* Project field entry */
-                       if (len > TDN_PROJECT_MAX - 1) {
-                           (void) fprintf(stderr, "table_descr_load(%s) - \
-Project field exceeds %d for '%s'\n", file, TDN_PROJECT_MAX - 1,
-                                       node->project);
-                           break;
-                       }
-                       mm_memcpy(node->project, line, len + 1);
-                       project_len = len;
-                       field = 1;
-                       continue;
-                   } else if (field == 1) {
-                       /* Short description entry */
-                       if (len > TDN_DESCR_S_MAX - 1) {
-                           (void) fprintf(stderr, "table_descr_load(%s) - \
-Short description field exceeds %d for '%s'\n", file, TDN_DESCR_S_MAX - 1,
-                                       node->project);
-                           break;
-                       }
-                       mm_memcpy(node->descr_s, line, len + 1);
-                       field = 2;
-                       continue;
-                   } else if (field == 2) {
-                       /* Long description entry */
-                       if (descr_l_len + len + 1 > TDN_DESCR_L_MAX - 1) {
-                           (void) fprintf(stderr, "table_descr_load(%s) - \
-Long description field exceeds %d for '%s'\n", file, TDN_DESCR_L_MAX - 1,
-                                       node->project);
-                           break;
-                       }
-                       mm_memcpy(&node->descr_l[descr_l_len], line, len);
-                       descr_l_len += len;
-                       node->descr_l[descr_l_len++] = '\n';
-                       continue;
-                   }
-               }
-               if (node != NULL)
-                   table = table_free(table);
-           } else {
-               (void) fprintf(stderr,
-                              "table_descr_load(%s) - hashtable_init()\n",
-                              file);
-               free(table);
-               table = NULL;
-           }
-       } else
-           (void) fprintf(stderr, "table_descr_load(%s) - malloc(table)\n",
-                          file);
-       (void) fclose(fh);
-    }
-
-    return table;
-}
-
-static hashtable_t *table_free(hashtable_t *table)
-{
-    if (table != NULL) {
-       (void) hashtable_destroy(table, TRUE);
-       free(table);
-    }
-
-    return NULL;
-}
-
-
-static list_t *list_load(const char *file, unsigned int cols, unsigned int key)
-{
-    list_t *list = NULL;
-    list_node *node = NULL;
-    FILE *fh;
-
-    if (cols >= COLS_MAX || key >= COLS_MAX) {
-       (void) fprintf(stderr, "list_load(%s) - cols|key >= COLS_MAX!\n",
-                      file);
-       return NULL;
-    }
-
-    if ((fh = fopen(file, "r")) != NULL) {
-       if ((list = malloc(sizeof(list_t))) != NULL) {
-           DLIST_INIT(list);
-           for (;;) {
-               int i;
-               size_t len;
-
-               if (node == NULL && (node = (list_node *)pool_alloc(&list_pool,
-                               FALSE)) == NULL) {
-                   (void) fprintf(stderr,
-                                  "list_load(%s) - pool_alloc()\n",
-                                  file);
-                   break;
-               }
-               if (fgets(node->line, LINE_MAX - 1, fh) == NULL) {
-                   node = (list_node *)pool_free((pnode_t *)node);
-                   break;
-               }
-               len = mm_strlen(node->line);
-               if (len > 0 && node->line[len - 1] == '\n')
-                   len--;
-               if (len > 0 && node->line[len - 1] == '\r')
-                   len--;
-               node->line[len] = '\0';
-               if (*node->line == '#' || *node->line == '\0')
-                   continue;
-               if (mm_strasplq(node->columns, node->line, cols) != cols) {
-                   (void) fprintf(stderr,
-                                  "list_load(%s) - Invalid line '%s'\n",
-                                  file, node->line);
-                   break;
-               }
-               for (i = 0; i < cols; i++)
-                   node->lengths[i] = mm_strlen(node->columns[i]);
-               node->hash = hashtable_hash(node->columns[key],
-                       node->lengths[key]);
-               DLIST_APPEND(list, (node_t *)node);
-               node = NULL;
-           }
-           if (node != NULL)
-               list = list_free(list);
-       } else
-           (void) fprintf(stderr, "list_load(%s) - malloc(list)\n",
-                          file);
-       (void) fclose(fh);
-    }
-
-    return list;
-}
-
-static list_t *list_free(list_t *list)
-{
-    if (list != NULL) {
-       node_t *node, *tnode;
-
-       for (node = DLIST_TOP(list); node != NULL; node = tnode) {
-           tnode = DLIST_NEXT(node);
-           (void) pool_free((pnode_t *)node);
-       }
-       free(list);
-    }
-
-    return NULL;
-}
diff --git a/site/new/build/mmsite.conf b/site/new/build/mmsite.conf
deleted file mode 100644 (file)
index 586b8b5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# General configuration options about the site
-
-TITLE          "Matthew Mondor's Software Site"
-BGCOLOR                #f0f0ff
-TEXT           #000000
-LINK           #3535c5
-VLINK          #700080
-MENU_BGCOLOR   #d0d0f0
-MENU_TEXT      #000066
-FONT           "helvetica, arial"
-HTDOCS         ../htdocs
-DEFAULT_LANG   en
diff --git a/site/new/build/site_faq.txt b/site/new/build/site_faq.txt
deleted file mode 100644 (file)
index ad51485..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# One FAQ entry per line, one column:
-# <faq>
-#
-mmftpd
-mmmail
-mmstatd
diff --git a/site/new/build/site_languages.txt b/site/new/build/site_languages.txt
deleted file mode 100644 (file)
index 27884a1..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# One language description per line, one column:
-# <language>
-#
-english
-french
diff --git a/site/new/build/site_mirrors.txt b/site/new/build/site_mirrors.txt
deleted file mode 100644 (file)
index 8e6834f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# One line per entry, three columns:
-# <name> <URL> <provider>
-#
-canada         http://mmondor.dynup.net/               "Ryan Werber"
-united-states  http://gobot.accela.net/                "Matthew J Backes"
-holland                http://mmondor.oostendorp-ict.nl/       "Jeroen Oostendorp"
diff --git a/site/new/build/site_pages.txt b/site/new/build/site_pages.txt
deleted file mode 100644 (file)
index 8d18ccc..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# One entry per line, one column:
-# <name>
-#
-index
-software
-donations
-contributors
-philosophy
-cvs
-projects
-mirrors
-contact
diff --git a/site/new/build/site_software.txt b/site/new/build/site_software.txt
deleted file mode 100644 (file)
index 19c965c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Each software category, one entry per line, two columns:
-# <category> <location>
-#
-stable         software/stable
-development    software/devl
-old            software/old
diff --git a/site/new/build/soft_development.txt b/site/new/build/soft_development.txt
deleted file mode 100644 (file)
index 8f9ebe9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# One project per line, three columns per project:
-# <projname> <status> <version>
-#
-mmftpd devl 1.0
diff --git a/site/new/build/soft_old.txt b/site/new/build/soft_old.txt
deleted file mode 100644 (file)
index 0874594..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# One project per line, three columns per project:
-# <projname> <status> <version>
-#
-ginseng-ftpd   devl 1.0
diff --git a/site/new/build/soft_stable.txt b/site/new/build/soft_stable.txt
deleted file mode 100644 (file)
index 0874594..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# One project per line, three columns per project:
-# <projname> <status> <version>
-#
-ginseng-ftpd   devl 1.0
diff --git a/site/philosophy.html b/site/philosophy.html
deleted file mode 100644 (file)
index bb21770..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-
-<html><head>
-<!--   $Id: philosophy.html,v 1.5 2003/06/04 12:17:47 mmondor Exp $
-       Copyright (c) 2002-2003 Matthew Mondor,  ALL RIGHTS RESERVED.
--->
-<title>Matthew Mondor's Software Site - Philosophy</title>
-<link rel="shortcut icon" href="/favicon.ico">
-</head>
-
-<!-- Begin -->
-<body bgcolor="#f0f0ff" text="#000000" link="#3535c5" vlink="#700080">
-<table border="0" cellspacing="5" cellpadding="5">
-<tbody><tr>
-
-<!-- Left column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Sections</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<p><font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html">Main</a>&nbsp;<br>
-&nbsp;<a href="software.html">Software</a>&nbsp;<br>
-&nbsp;<a href="donations.html">Donations</a>&nbsp;<br>
-&nbsp;<a href="contributors.html">Contributors</a>&nbsp;<br>
-&nbsp;<a href="philosophy.html"><em>Philosophy</em></a>&nbsp;<br>
-&nbsp;<a href="cvs.html">CVS</a>&nbsp;<br>
-&nbsp;<a href="projects.html">Projects</a>&nbsp;<br>
-&nbsp;<a href="mirrors.html">Mirrors</a>&nbsp;<br>
-&nbsp;<a href="mailto:mmondor@gobot.ca">Contact</a>&nbsp;<br>
-</font></td></tr></tbody></table>
-<br><img src="images/sigil.jpg" alt="Image Copyright (c) 2002-2003, Matthew Mondor">
-</td></p>
-
-<!-- Middle column -->
-<td valign="top">
-<center>
-<font face="helvetica, arial" size="4">Philosophy behind mmsoftware</font><br>
-</center>
-<font face="helvetica, arial">
-<p>
-Several primary goals were the basis to write my suite of public internet
-services. One consisted of a challenge to learn UNIX APIs deeply at the time
-I decided to write my own. This is no longer the case, but probably that the
-most driving factor still has to do with my need to run such services.
-</p><p>
-Of course there exists a variety of solutions for each of the standard
-protocols. However, most of them seemed historical, based on code which made
-it though the years through extreme amounts of patching and kludges. This
-generally results in solutions which are hard to configure, and have gone
-though a long history of security-related issues. Most of them even support
-obsolete protocols, or experimental ones which never have been widely used.
-</p><p>
-Moreover, several of them were subject to strict licensing issues. Writing
-my own software I have the full rights to do whatever I want with it, as
-well as eventually distribute closed-source special editions commercially.
-But I didn't want to be the only one to be able to do this, hence I decided
-to release my software under a BSD-style license (Berkeley Source Distribution
-license), allowing others to modify it and distribute it under source or
-binary form as wanted, only requireing them to add an aknowledgement to their
-product documentation:
-</p><p><font face="times">
-&nbsp;&nbsp;This product includes software written by Matthew Mondor.
-</font></p><p>
-It however obviously is encouraged to report to me the various bug fixes
-or enhancement patch so that the main publicly available tree also evolve.
-</p><p>
-Considering security aspects, most traditional UNIX internet services software
-ran as the superuser, and required standard UNIX users to be added for each
-remote user. I strongly beleive that most administrators enjoy being able to
-only create virtual users rather than real UNIX shell ones for each of their
-users. My daemons therefore only allow virtual users. Moreover, none of them
-require to run as the superuser after their initial startup.  Most of them
-have support for chroot(2) as well, for administrators who need it.
-</p><p>
-These are public services afterall. I personally use them to contribute
-software and services which are often free of charge, and would find it quite
-discouraging if my services were exploited and servers virtually destroyed.
-I think that many administrators are in the same position and would like to
-run safe services.
-</p><p>
-Special care is taken when writing this software to avoid memory leaks (which
-could be a threat to service uptime and autonomy), and to check every
-error condition possible. As the services should remain up, system resources
-error conditions are treated in a safe way; The current operation is cancelled
-to not execute code which requires these new resources to be allocated,
-previous allocated ones are released if any (but not all) were obtained for
-the current operation as well, and the service keeps running as usual. This
-also implies using I/O operations which can timeout where required. Also,
-libc functions with uncertain delay periods get executed by an asynchroneous
-parallel system when userspace threading systems are used, to prevent locking
-the main process, allowing service to remain fluid among the multiple
-simultaneous connections being served. Some effort was also made to keep the
-code clean.
-</p><p>
-C was chosen to write these for several reasons. I am well used to it, having
-used it for many years, was a primary one. A second worthwhile reason is that
-the UNIX, POSIX and BSD APIs are intended for C programs. It is also possible
-for the programmer to optimize C code decently rather than only relying on
-compiler effeciency to do it, gaining speed advantage without having to use
-less maintainable and unportable assembly. When well written, C programs are
-also portable. C++ could have suited, but would result in generally less
-efficient code. I also like to control my own use of memory useage, object
-allocation and garbage collection, hence it was not worth it to use C++.
-Where possible, ANSI-C compliance is observed.
-</p><p>
-Matthew Mondor
-</p>
-</font>
-</td>
-
-<!-- Right column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Languages</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html"><em>English</em></a>&nbsp;<br>
-&nbsp;<a href="index_fr.html">French</a>&nbsp;<br>
-</font></td></tr></tbody></table></p>
-<p><font face="helvetica, arial" color="#000066"><b>Mirrors</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="http://mmondor.dynup.net/index.html">Canada</a>&nbsp;<br>
-&nbsp;<a href="http://gobot.accela.net/index.html"><nobr>United-States</nobr></a>&nbsp;<br>
-&nbsp;<a href="http://mmondor.oostendorp-ict.nl/index.html">Holland</a>&nbsp;<br>
-</font></td></tr></tbody></table></td></p>
-
-<!-- End -->
-</tr><tr><td valign="bottom" align="left" colspan="3">
-<font face="helvetica, arial" size="-2">
-$Id: philosophy.html,v 1.5 2003/06/04 12:17:47 mmondor Exp $<br>
-This site Copyright (c) 2002-2003, Matthew Mondor, ALL RIGHTS RESERVED.
-</font></td></tr></tbody></table>
-</body></html>
diff --git a/site/projects.html b/site/projects.html
deleted file mode 100644 (file)
index 199eeb2..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-
-<html><head>
-<!--   $Id: projects.html,v 1.6 2003/06/04 12:17:47 mmondor Exp $
-       Copyright (c) 2002-2003 Matthew Mondor,  ALL RIGHTS RESERVED.
--->
-<title>Matthew Mondor's Software Site - Projects</title>
-<link rel="shortcut icon" href="/favicon.ico">
-</head>
-
-<!-- Begin -->
-<body bgcolor="#f0f0ff" text="#000000" link="#3535c5" vlink="#700080">
-<table border="0" cellspacing="5" cellpadding="5" width="100%">
-<tbody><tr>
-
-<!-- Left column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Sections</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<p><font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html">Main</a>&nbsp;<br>
-&nbsp;<a href="software.html">Software</a>&nbsp;<br>
-&nbsp;<a href="donations.html">Donations</a>&nbsp;<br>
-&nbsp;<a href="contributors.html">Contributors</a>&nbsp;<br>
-&nbsp;<a href="philosophy.html">Philosophy</a>&nbsp;<br>
-&nbsp;<a href="cvs.html">CVS</a>&nbsp;<br>
-&nbsp;<a href="projects.html"><em>Projects</em></a>&nbsp;<br>
-&nbsp;<a href="mirrors.html">Mirrors</a>&nbsp;<br>
-&nbsp;<a href="mailto:mmondor@gobot.ca">Contact</a>&nbsp;<br>
-</font></td></tr></tbody></table>
-<br><img src="images/sigil.jpg" alt="Image Copyright (c) 2002-2003, Matthew Mondor">
-</td></p>
-
-<!-- Middle column -->
-<td valign="top">
-<center>
-<font face="helvetica, arial" size="4">Various Projects and Background</font><br>
-</center>
-<font face="helvetica, arial">
-<p>
-Here first follows an overview of my computer-related background
-</p><p>
-A brief overview of my computer-related background: I touched my first computer
-at the age of 8, an Apple][+, on which I immediately wanted to code games,
-mostly of the text type. I then learned 6802 assembly, as AppleSoft BASIC was
-pretty much useless, and Z80 assembly, which was available through a
-bridgeboard. I then wrote disk utilities (backup, data retreival).
-</p><p>
-I then at my great joy had my first Amiga when I was 15, on which I first used
-mildly AmigaBASIC. Of course a year later I was learning C, and using the RKMS
-wrote AstralPortal (Voice/Fido/Data Modem software) in the few following years.
-I then did some 2d vector graphics using 68000 assembly, C and sometimes
-BlitzBasic (which accepted direct assembly instructions and had nice blit
-routines. Some playing with ARexx was then done. The last thing I developed
-on Amiga was audio sample manipulation and compression utilities in C, along
-with a programmable binaural/hemisync braintrainer, and some custom GUI
-library. Another latest project was a control server which allowed several
-RS232 terminals to be synchronized with a main multitasking server application
-with abstract tty-specific code translation. What a great box that was.
-</p><p>
-Then finally, I decided to get an i386DX/40/8megs although it was already
-deprecated, and started doing some Turbo-C and 8088 assembly on MS-DOS,
-and wrote trivial 2d 8-bit functions library along with a graphic
-block-oriented editor for game programming. Some scrolling, sprite and
-collision code was added, and it was a ready system to write games, but none
-were ever written using it, but demos. As I always was avoiding windows since,
-but had to at least confront it for a while, I finally bought an AMD-K6-2/450
-and learned some Win32 API, tried various compilers with GUI frontends. I
-unfortunately was pretty discouraged after a year or so, and was not
-programming anything useful; Until I made a discovery... Linux 2.0.35 (RH6)
-in December 1999.
-</p><p>
-I used RedHat 6 for a few months, getting aquainted with GCC (which fortunately
-had the same base interface than DICE dcc from Matt Dillon which I was using
-on the Amiga). And, glibc info/man pages. Linux finally made me discover that
-a PC could finally be worth it, as much as Amiga was. I soon found that on
-an AmigaOS shell I couldn't remember the commands, erroneously typing unix
-ones. The switch was made. I then tried Debian Potato, which of course made
-me forget RH for good, and eventually did my own distribution, Ginseng, a
-security and server related distribution. Between Debian and Ginseng I started
-to write a few meaningful TCP server-oriented utilities. I then discovered
-NetBSD.
-</p><p>
-Obviously I then had found my ideal OS, which I am still heavily using today
-on all my systems. I finally was free from glibc, which was everyday getting
-more bloated without true additionnal functionallity.
-I tried other BSD variants and was more convinced that NetBSD still was my
-choice. My current publically available software was written using it.
-Current projects include mmmail, which is now being totally redesigned from
-scratch (for v2), mmftpd, Xisop (a portable non-SMP multitasking preemptive
-microkernel similar to AmigaOS), an arbitrary math library and C-like
-simplified tokernizer/interpretor language for secure distributed network
-clients, along with their distributed server counterpart. I mostly emphasize
-my projects on security (good tactics as running virtual services as
-non-privileged users, encryption, etc are useful).
-</p><p>
-I also use and test various tunnelling/VPN solutions, am working on a secure
-NFS alternative, and various work-related projects. I try to eventually
-provide easy solutions to common administration nightmares such as sendmail
-administration, localized central data servers and similar tasks. Some work
-has also been done on a state-persistant secure HTTP authentication protocol
-where unique cookies are exchanged between each page under SSL, and their
-origin/expiration verified on the server-side, possibly that an ssl-httpd will
-eventually become available for safe remote administration of mmmail, mmftpd
-and other server daemons I write.
-</p><p>
-I often don't mind to redesign existing systems, re-invent them or be
-inspired by their concepts, when a happy result can be obtained afterwards.
-Other non-computer related interests exist, including swimming, martial
-arts, meditation (often a necessity for relaxation), international foods,
-microbrewered and rare dark, rich beers, especially the stout type.
-Writing also has always been a great passion all my life, from adventure
-novels (unpublished) to technical documentation (some only has been made
-available publically). And music. What a great way to express soul states,
-composing and producing various music types, especially Fusion-Jazz remains
-a never-ending story.
-</p><p>
-Matt
-</p>
-</font>
-</td>
-
-<!-- Right column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Languages</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html"><em>English</em></a>&nbsp;<br>
-&nbsp;<a href="index_fr.html">French</a>&nbsp;<br>
-</font></td></tr></tbody></table></p>
-<p><font face="helvetica, arial" color="#000066"><b>Mirrors</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="http://mmondor.dynup.net/index.html">Canada</a>&nbsp;<br>
-&nbsp;<a href="http://gobot.accela.net/index.html"><nobr>United-States</nobr></a>&nbsp;<br>
-&nbsp;<a href="http://mmondor.oostendorp-ict.nl/index.html">Holland</a>&nbsp;<br
->
-</font></td></tr></tbody></table></td></p>
-
-<!-- End -->
-</tr><tr><td valign="bottom" align="left" colspan="3">
-<font face="helvetica, arial" size="-2">
-$Id: projects.html,v 1.6 2003/06/04 12:17:47 mmondor Exp $<br>
-This site Copyright (c) 2002-2003, Matthew Mondor, ALL RIGHTS RESERVED.
-</font></td></tr></tbody></table>
-</body></html>
diff --git a/site/software.html b/site/software.html
deleted file mode 100644 (file)
index 7781a2a..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-
-<html><head>
-<!--   $Id: software.html,v 1.15 2003/12/12 15:58:39 mmondor Exp $
-       Copyright (c) 2002-2003 Matthew Mondor,  ALL RIGHTS RESERVED.
--->
-<title>Matthew Mondor's Software Site - Software</title>
-<link rel="shortcut icon" href="/favicon.ico">
-</head>
-
-<!-- Begin -->
-<body bgcolor="#f0f0ff" text="#000000" link="#3535c5" vlink="#700080">
-<table border="0" cellspacing="5" cellpadding="5" width="100%">
-<tbody><tr>
-
-<!-- Left column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Sections</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<p><font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html">Main</a>&nbsp;<br>
-&nbsp;<a href="software.html"><em>Software</em></a>&nbsp;<br>
-&nbsp;<a href="donations.html">Donations</a>&nbsp;<br>
-&nbsp;<a href="contributors.html">Contributors</a>&nbsp;<br>
-&nbsp;<a href="philosophy.html">Philosophy</a>&nbsp;<br>
-&nbsp;<a href="cvs.html">CVS</a>&nbsp;<br>
-&nbsp;<a href="projects.html">Projects</a>&nbsp;<br>
-&nbsp;<a href="mirrors.html">Mirrors</a>&nbsp;<br>
-&nbsp;<a href="mailto:mmondor@gobot.ca">Contact</a>&nbsp;<br>
-</font></td></tr></tbody></table>
-<br><img src="images/sigil.jpg" alt="Image Copyright (c) 2002-2003, Matthew Mondor">
-</td></p>
-
-<!-- Middle column -->
-<td valign="top">
-<center>
-<font face="helvetica, arial" size="5">The Software</font><br>
-</center>
-<font face="helvetica, arial">
-<p>
-This page contains the various official mmsoftware sources. The third-party
-software provided by the contributors can be found in the
-<a href="contributors.html">contributors</a> area. Access to the current
-official mmsoftware sources CVS repository is available (via pserver). Details
-about CVS can be found under the <a href="cvs.html">CVS</a> section. It is
-also possible to obtain the source archives of the old releases for reference
-only, in the software archive: <a href="software/">software/</a>.
-</p><p><center><b>Featured software:</b></center></p><p>
-This software is actively maintained and in constant development. This also
-means that bug reports are taken into consideration as fast as
-possible and new version released accordingly, shortly after bug discovery,
-when a suitable solution has been implemented to solve the issue.
-</p>
-</font>
-<table border="1" bgcolor="#d0d0f0" width="100%">
-<font face="helvetica, arial">
-<tr>
-<th><a href="software/devl/mmftpd-0.0.17.tgz">mmftpd</a></th>
-<td align="center">0.0.17</td>
-<td align="center">Devl</td>
-<td align="center">
-<a href="software/misc/mmftpd-changelog.txt">ChangeLog</a></td>
-<td align="center">
-<a href="software/devl/mmftpd-0.0.17.tgz.md5.txt">MD5</a></td>
-</tr>
-<tr><td align="center" colspan="5">
-Unprivileged virtual users FTP server
-</td></tr>
-<tr><td bgcolor="#c6e0e0" colspan="5"><font face="helvetica, arial" size="-1">
-<p>
-mmftpd was written from scratch from the ground up, and consists of a
-featureful yet very security-aware FTP server. It is released under the
-terms and conditions of the BSD license with advertizing clause to keep
-credits to the author. It ensures to run under a single unprivileged user,
-and provides FTP virtual users, as opposed to traditional UNIX/system ones,
-which each appear jailed in their home directory using extensive path sanity
-checking. It optionally also can chroot(2) at program startup for the whole
-service and all users to be setup under a real alternative root jail.
-Runs great on BSD and Linux systems and is fairly small in size. Well
-documented via UNIX manual pages.
-</p><p>
-The server can limit the connection rate from an address and also has
-bandwidth traffic shaping capabilities for both control and data ports,
-on a per-connection and global basis. It also can limit the connections
-on several factors (maximum number of addresses, number of allowed
-connections per address and how many simultaneous connections from the same
-FTP user to accept). Client hostname resolving is optional for speed, and
-is performed using asynchroneous methods when enabled.
-</p><p>
-For each FTP user a number of permission parameters can be customized,
-including the maximum upload and download speed, umask, rights to
-change umask, upload, modify, maximum home directory tree size (even safe
-among multiple simultaneous connections of the same user). Various techniques
-were implemented to prevent common Denial Of Service attempts.
-</p><p>
-Various statistics are reliably maintained using the mmstat facility,
-and the administrator can set the verbosity of wanted events and statistics
-to be output via syslog. Moreover it uses efficient custom I/O buffering
-around filedescriptors for speed. Users are stored in a configuration file
-with their permissions, using native crypt(3) password hashes
-(both MD5 and DES), so that it is possible to create virtual mmftpd users
-from system ones using the same password hashes. The server options are
-configured via a second configuration file.
-</font></td></tr>
-</table><br><table border="1" bgcolor="#d0d0f0" width="100%">
-<th><a href="software/devl/mmmail-0.0.23.tgz">mmmail</a></th>
-<td align="center">0.0.23</td>
-<td align="center">Devl</td>
-<td align="center">
-<a href="software/misc/mmmail-changelog.txt">ChangeLog</a></td>
-<td align="center">
-<a href="software/devl/mmmail-0.0.23.tgz.md5.txt">MD5</a></td>
-</tr>
-<tr><td align="center" colspan="5">
-Unprivileged virtual SMTP+POP3 server suite using MySQL
-</td></tr>
-<tr><td bgcolor="#c6e0e0" colspan="5"><font face="helvetica, arial" size="-1">
-<p>
-mmmail was written from scratch from the ground up, and consists of a
-suite of SMTP and POP3 servers which can fully run under a unprivileged
-user. It is released under the terms and conditions of the BSD license with
-advertizing clause to keep credits to the author. It provides virtual mail
-users, contrary to traditional UNIX/system ones. It optionally supports
-chroot(2) at program startup to enclose itself into a jail. It runs great
-on both BSD and Linux systems and is fairly small in size. Well documented
-via UNIX manual pages.
-</p><p>
-The servers can limit their clients connection rate on a per-address basis,
-and also support bandwidth traffic shaping capabilities in both directions
-(connection-specific and global ones). It also can limit the connections
-on several factors (maximum number of addresses, number of allowed
-connections per address and how many simultaneous connections from the same
-POP3 user to accept). Client hostname resolving is optional for speed, and
-is performed using asynchroneous methods when enabled. Moreover, the
-administrator may decide weither to check for HELO and/or MAIL MX DNS
-records before accepting SMTP mail from a client. Use of HELO may be
-disabled or enforced. Various techniques were implemented to prevent common
-Denial Of Service attempts.
-</p><p>
-For each mail user/password pair can exist several email addresses at several
-virtual hosts, and aliasing is supported to map unexisting addresses to others,
-even optionally using wildcard pattern matching. The administrator can also
-set the address and/or hostname masks through which mail with empty FROM
-address is sent. Each mailbox can be set customizeable quotas (mailbox total
-size and total number of messages). All storage (users, mailboxes, and mail
-itself) uses MySQL, which permits a global database server to be used, even
-remotely. A persistant connection is established and maintained with the
-server by each daemon, and re-established if ever necessary.
-</p><p>
-Various statistics are reliably maintained using the mmstat facility,
-and the administrator can set the verbosity of wanted events and statistics
-to be output via syslog. Moreover it uses efficient custom I/O buffering
-around filedescriptors for speed. Each daemon is configured through it's
-own configuration file. User password hashes are stored in native crypt(3)
-format (both MD5 and DES work) so it is possible to translate system users
-to mmmail virtual ones keeping the same hash.
-Also, mmpop3d supports unstandard POP3 PAGE command (better than TOP) which
-was especially implemented for human POP3 clients.
-</p><p>
-Unfortunately, support for relaying will only be added for mmmail2, a future
-re-implementation of mmmail which also should support multiple authentication
-and storage methods, as well as many other features including IMAP.
-If you are interested in knowing more about mmmail2 ongoing engineering
-(diagrams and documentation), and to make suggestions, you can download this
-<a href="software/devl/mmmail-design.pdf">mmmail-design.pdf</a> document.
-</td></tr>
-</table><br>
-<table border="1" bgcolor="#d0d0f0" width="100%">
-<th><a href="software/devl/mmstatd-0.0.8.tgz">mmstatd</a></th>
-<td align="center">0.0.8</td>
-<td align="center">Devl</td>
-<td align="center">
-<a href="software/misc/mmstatd-changelog.txt">ChangeLog</a></td>
-<td align="center">
-<a href="software/devl/mmstatd-0.0.8.tgz.md5.txt">MD5</a></td>
-</tr>
-<tr><td align="center" colspan="5">
-Statistics maintenance server daemon and client library
-</td></tr>
-<tr><td bgcolor="#c6e0e0" colspan="5"><font face="helvetica, arial" size="-1">
-<p>
-mmstatd was originally written for mmftpd and mmmail to asynchroneously
-maintain statistical counters in an efficient manner. I however also
-release it separately as it is used by some other people in their projects.
-These include an IRC network services system which although using db4 for
-most data storage uses mmstat(3) library for various statistics counters.
-</p><p>
-It does not require any additional libraries, and provides a simple API
-for applications to either update counters or query statistics. The update
-requests are done using an AF_LOCAL/UNIX datagram to the mmstatd service's
-log socket, similarly to the way syslog(3) works. Statistics are queried
-via an AF_LOCAL/UNIX stream on another mmstatd socket. Permissions for access
-to both sockets can be different.
-</p><p>
-The service consists of a librarian and logger. The logger accumulates
-requests filling a recovery log, while the librarian processes those logs
-asynchroneously and syncs the disk database with them from time to time.
-In case of a crash, the recovery logs which weren't synchronized yet to
-disk are used to recover from the crash. Provided with it is a utility
-to query and update statistics from the shell as well.
-</td></tr>
-</table><br><p><center><b>Unmaintained software:</b></center></p>
-<p>
-This section contains software which works but which I am no longer
-maintaining. These are Linux-specific and are getting old. I keep them
-here because a fair amount of people find these handy and download
-them.
-</p>
-<table border="1" bgcolor="#d0d0f0" width="100%">
-<th><a href="software/stable/mmtcpfwd-0.1.0.tar.gz">mmtcpfwd</a></th>
-<td align="center">0.1.0</td>
-<td align="center">Stable</td>
-<td align="center">
-<a href="software/misc/mmtcpfwd-changelog.txt">ChangeLog</a></td>
-<td align="center">
-<a href="software/stable/mmtcpfwd-0.1.0.tar.gz.md5.txt">MD5</a></td>
-</tr>
-<tr><td align="center" colspan="5">
-Port forwarder, MASQ fake identd and FTP proxy for Linux
-</td></tr>
-<tr><td bgcolor="#c6e0e0" colspan="5"><font face="helvetica, arial" size="-1">
-<p>
-Written from scratch, consists of a superserver daemon made of two parts,
-one process running as the superuser (to perform tasks like modifying
-firewall rules) and the other running as an unprivileged user performing
-all the work. This privilege separation system is quite effective for
-a secure setup. Linux 2.2 specific (can work with 2.4+ but without the
-transparent proxying support). Released under the terms of the GPL
-(GNU Public License).
-</p><p>
-mmtcpfwd provides transparent TCP/IP connection proxying from a MASQ enabled
-gateway to other machines, including FTP connections, via a special userspace
-passive FTP connections proxy supporting PASV, LPSV and EPSV, and masking the
-actual FTP server LAN address by supplying the gateway's address instead.
-Supports SMP where hardware permits. Uses a main configuration file to
-configure all it's parameters. Also provides an optional random UNIX-ident
-protocol daemon, allowing masqueraded connections behind the gateway to
-use services requireing identd to run.
-</p><p>
-For each forwarded port, a non-privileged process is setup to listen to
-and forward multiple connections to their configured destination. This
-destination can consist of a remote or local host, and it is possible to
-make it resolve IP address by hostname or to specify absolute IP addresses
-for speed.
-</p><p>
-Several interesting techniques are implemented to counter Denial of Service
-attacks: Total number of forwarded simultanious connections per port can be
-set, as well as per address. Also permits to deny automatically an IP address
-overflowing connections with a threshold, in which case each active connection
-from that address are cleanly closed before applying the firewall deny rule,
-executing a command of our choice. Allows to fake services like portsentry to
-immediately DENY an IP address that connects, sending a configurable message
-before closing and applying the DENY rule. Can also automatically undeny IP
-addresses of offendants after a certain amount of minutes, or indefinitely.
-As many IP addresses to never deny as we want can be specified.
-</p><p>
-Uses syslog logging, to keep log of connections/bytes transfered, elapsed
-time, etc... Hostnames can be resolved or not, on a per-port basis.
-Supports kernel's IP Transparent Proxying support to fake client's IP address
-when forwarding. Aimed towards security as much as possible.
-Fairly small, executable around 30k only.
-</p>
-</font></td></tr>
-</table><br><table border="1" bgcolor="#d0d0f0" width="100%">
-<th><a href="software/devl/ginseng-ftpd-1.6.tar.gz">ginseng-ftpd</a></th>
-<td align="center">1.6</td>
-<td align="center">Devl</td>
-<td align="center">
-<a href="software/misc/ginseng-ftpd-changelog.txt">ChangeLog</a></td>
-<td align="center">
-<a href="software/devl/ginseng-ftpd-1.6.tar.gz.md5.txt">MD5</a></td>
-</tr>
-<tr><td align="center" colspan="5">
-Security-enhanced Linux ftpd based on bsd-ftpd (NetBSD)
-</td></tr>
-<tr><td bgcolor="#c6e0e0" colspan="5"><font face="helvetica, arial" size="-1">
-<p>
-This server originally consisted of a port of BSD-FTPd to Linux, and various
-custom features were added which I personally needed at the time. Since I
-wrote mmftpd which much better suits my needs I no longer maintain
-ginseng-ftpd. It's still available though, for people who need to run FTP
-services with real users (where security is generally not that much of a
-concern). An FTP server allowing use of standard UNIX system users obviously
-required to run as the superuser. Run mmftpd if you need better security.
-Was released under the terms of the BSD license.
-</p><p>
-I here describe a list of the various changes that I made on the original
-BSD-FTPd code: The popular recently discovered single-byte vulnerability of
-bsd-ftpd was fixed, some better sanity checking around seteuid(),
-setegid() and fork() was added. Was fixed against the recursive LIST/NLST
-problems which alot of FTP servers are vulnerable to, including BSD-FTPd
-at the time. Now only requires a single configuration file (/etc/ftpusers)
-for all account options, and users MUST be present in it to be allowed
-FTP access (contrary to traditional behavior). The configuration file now
-uses one user per line, and one column per user configurable option.
-</p><p>
-Support for read-only accounts, umask specification and homedir total size
-limits on a per/user basis and number of connections per user was added,
-note that the tree size quotas are only safe if only one simultaneous logins
-of that user are allowed. Shared memory and semaphores would have been
-required otherwise which would have strongly impacted performance.
-This is not the case for mmftpd where threads are used and quotas are
-safe no matter what. The server was modified to only accept to be launched
-by the superuser.
-</p><p>
-The following command switches/parameters were added when starting the
-daemon: -q to not display ftpd type/version to clients, -n to not resolve
-hostnames for speed, -x to allow masquerading actual LAN IP address to
-0.0.0.0 for passive replies (not that not all clients will work, I
-recommend using mmtcpfwd passive FTP proxying to masquerade those to
-the actual gateway's IP address instead, where all clients will work.
-Finally, -q was added to specify which port to listen to.
-</p>
-</font></td></tr>
-</table>
-</font>
-</td>
-
-<!-- Right column -->
-<td valign="top" bgcolor="#d0d0f0">
-<font face="helvetica, arial" color="#000066"><b>Languages</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="index.html"><em>English</em></a>&nbsp;<br>
-&nbsp;<a href="index_fr.html">French</a>&nbsp;<br>
-</font></td></tr></tbody></table></p>
-<p><font face="helvetica, arial" color="#000066"><b>Mirrors</b></font><br>
-<table border="0" cellspacing="4" cellpadding="2"><tbody><tr><td>
-<font face="helvetica, arial" size="-1">
-&nbsp;<a href="http://mmondor.dynup.net/index.html">Canada</a>&nbsp;<br>
-&nbsp;<a href="http://gobot.accela.net/index.html"><nobr>United-States</nobr></a>&nbsp;<br>
-&nbsp;<a href="http://mmondor.oostendorp-ict.nl/index.html">Holland</a>&nbsp;<br
->
-</font></td></tr></tbody></table></td></p>
-
-<!-- End -->
-</tr><tr><td valign="bottom" align="left" colspan="3">
-<font face="helvetica, arial" size="-2">
-$Id: software.html,v 1.15 2003/12/12 15:58:39 mmondor Exp $<br>
-This site Copyright (c) 2002-2003, Matthew Mondor, ALL RIGHTS RESERVED.
-</font></td></tr></tbody></table>
-</body></html>
diff --git a/tests/entropy/README b/tests/entropy/README
deleted file mode 100644 (file)
index 96844b5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-Attempts to generate enough rnd(4) entropy on NetBSD systems using
-CGD for encrypted swap.  Using it on a laptop.
-
-This implentation uses pseudo-random reads on a hard disk device
-in order to hopefully cause the rnd(4) device (which is among other
-devices fed by the wd* and sd* devices) to be fed entropy caused
-by unstability features of the heads.
-
-The program can be launched before starting the encrypted builds,
-then mounting the wanted CGD devices can be made, which shouldn't
-cause a lockup anymore while cgdconfig(8) creates random the
-cryptography keys with /dev/random.  The program can then be killed.
diff --git a/tests/entropy/entropy_disk.c b/tests/entropy/entropy_disk.c
deleted file mode 100644 (file)
index 0a44ba0..0000000
+++ /dev/null
@@ -1,629 +0,0 @@
-/* $Id: entropy_disk.c,v 1.5 2006/09/21 20:11:16 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006 Pulsar-Zone, Reg.
- * All rights reserved.
- *
- * Written by Matthew Mondor for Pulsar-Zone, Reg.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed for the NetBSD Project by
- *      Pulsar-Zone, Reg.
- * 4. The name of Pulsar-Zone, Reg. may not be used to endorse
- *    or promote products derived from this software without specific prior
- *    written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY PULSAR-ZONE, REG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL PULSAR-ZONE, REG
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Strategy:
- *
- * 1) First obtain wd* or sd* devices using sysctl(3) which could be used to
- *    produce entropy.  Error and exit if no such devices can be used.
- * 2) Report our PID and detach, allowing SIGTERM to kill us.
- * 3) In an endless loop, read various arbitrary blocks of random lenghts and
- *    at random positions from random disks.  We take care to toggle the
- *    reading direction often enough to give the heads an opportunity to seek
- *    in both directions.
- * 4) Upon receiving a SIGTERM signal, close the disk devices and exit.
- *
- * To obtain rather decent random values, we use the 4.2BSD random(3) PRNG
- * but seed it using /dev/urandom.  This prevents sucking up too much entropy
- * from rnd(4), which we're designed to fill rather than waste, afterall.
- * We periodically reseed the PRNG with /dev/urandom during the main loop as
- * well.
- *
- * XXX Consider using arc4random(3) instead.  However, possible problems could
- * occur using it:  it could void rnd(4) entropy, especially that at least
- * 1024 bytes of the arcfour keystream should be discarded to be random
- * enough.
- *
- * XXX Possibly add an option to tell the daemon to automatially exit after a
- * certain number of seconds or minutes elapsed.  We would use setitimer(2)
- * to receive a SIGALRM, acting the same as for SIGTERM upon its reception.
- *
- * XXX Make lseek(2)/read(2) errors silent via compile time option to not
- * disclose any information in case of disk problems for a final version of
- * this program.
- */
-
-#include <sys/mman.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <sys/queue.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-
-
-/*
- * Minimum block size to read (could be disk dependent but it doesn't matter
- * much for this task.
- */
-#define BLOCK_SIZE     16384
-/*
- * Maximum number of BLOCK_SIZE blocks to read in a single read(2)
- */
-#define BLOCK_MULTIPLE 16
-/*
- * Minimum and maximum number of reads to perform in a single direction before
- * switching direction.  If these are too low the disk head thrashing could be
- * excessive.
- */
-#define DIRECTION_MIN  256
-#define DIRECTION_MAX  4096
-/*
- * Minimum and maximum reseeding of PRNG from urandom(4) frequency (in reads).
- * If we set these this too low, the entropy we're trying to accumulate in
- * rnd(4) is sucked out as we create it, causing us to loop indefinitely for
- * nothing.
- */
-#define RESEED_MIN     32
-#define RESEED_MAX     256
-
-enum direction {
-       DIR_FORWARD = 0,
-       DIR_BACKWARDS = 1
-};
-
-typedef struct drive_entry {
-       SLIST_ENTRY(drive_entry) chain;
-       char            *name;
-       off_t           max, pos;
-       int             fd;
-       int             dir, dircnt;
-} disk_t;
-
-SLIST_HEAD(slisthead, drive_entry);
-
-#define BALIGN_CEIL(v, s)      ((((size_t)(v)) + (s) - 1) / (s) * (s))
-
-
-
-int                    main(int, char **);
-
-static int             prng_init(void);
-static void            prng_reseed(void);
-static void            prng_close(void);
-static void            signal_handler(int);
-static int             detach(const char *);
-static void            disk_open(const char *);
-static int             disks_open(void);
-static void            disks_close(void);
-static void            *buffer_alloc(size_t);
-static void            buffer_free(void *, size_t);
-
-
-
-static char            *pidfile = "/var/run/entropy_disk.pid";
-static int             maxdisks = 4;
-
-static struct slisthead        disks_list = SLIST_HEAD_INITIALIZER(drive_entry);
-static int             ndisks = 0;
-static disk_t          **disks_array = NULL;
-
-static int             urandom = -1;
-static int             reseed = 0;
-
-static size_t          pagesize = 0;
-
-static int             run = 1;
-
-
-
-int
-main(int argc, char **argv)
-{
-       char    c;
-       void    *readbuf;
-       int     ret = EXIT_FAILURE;
-
-       setprogname(argv[0]);
-
-       /* Parse commad line arguments */
-       while ((c = getopt(argc, argv, "p:n:?")) != -1) {
-               switch (c) {
-               case 'p':
-                       pidfile = optarg;
-                       break;
-               case 'n':
-                       maxdisks = strtol(optarg, NULL, 10);
-                       if (maxdisks < 1 || maxdisks > 100) {
-                               (void) fprintf(stderr,
-                                   "<maxdisks> must be between 1 and 100\n");
-                               return EXIT_FAILURE;
-                       }
-                       break;
-               case '?':
-                       /* FALLTHROUGH */
-               default:
-                       (void) fprintf(stderr,
-                           "Usage: %s [-p <pidfile>] [-n <maxdisks>]\n",
-                           getprogname());
-                       return EXIT_FAILURE;
-               }
-               argc -= optind;
-               argv += optind;
-       }
-
-       /*
-        * Initialization
-        */
-       if (prng_init() != 0)
-               return EXIT_FAILURE;
-
-       if (disks_open() != 0)
-               return EXIT_FAILURE;
-
-       if ((readbuf = buffer_alloc(BLOCK_SIZE * BLOCK_MULTIPLE)) == NULL)
-               goto end;
-       if (detach(pidfile) != 0)
-               goto end;
-
-       /* Main loop */
-       while (run) {
-               disk_t          *e;
-               int             blocks;
-               unsigned long   diff;
-
-               /* Choose a disk */
-               e = disks_array[random() % ndisks];
-
-               /* Choose a block size */
-               blocks = random() % BLOCK_MULTIPLE;
-
-               /*
-                * Choose a position relative to a previous one and doesn't
-                * exceed e->max (which already accounts for the block size
-                * and is already BLOCK_SIZE aligned).  Our new position must
-                * also be BLOCK_SIZE aligned.
-                */
-               diff = BALIGN_CEIL(random() % (e->max / DIRECTION_MIN),
-                   BLOCK_SIZE);
-               if (e->dir == DIR_BACKWARDS) {
-                       if ((e->pos -= diff) < 0)
-                               e->dir = DIR_FORWARD;
-               }
-               if (e->dir == DIR_FORWARD)
-                       e->pos = BALIGN_CEIL((e->pos + diff) % (e->max + 1),
-                           BLOCK_SIZE);
-               if (--e->dircnt < 0) {
-                       e->dir = (e->dir == DIR_FORWARD ?
-                           DIR_BACKWARDS : DIR_FORWARD);
-                       e->dircnt = DIRECTION_MIN +
-                           (random() % (DIRECTION_MAX - DIRECTION_MIN));
-               }
-
-               /* Seek and read block(s) */
-               if (lseek(e->fd, e->pos, SEEK_SET) != -1) {
-                       if (read(e->fd, readbuf, blocks * BLOCK_SIZE) !=
-                           blocks * BLOCK_SIZE)
-                               (void) fprintf(stderr,
-                                   "read(%s, %llu, %u): %s\n",
-                                   e->name, e->pos, blocks * BLOCK_SIZE,
-                                   strerror(errno));
-               } else
-                       (void) fprintf(stderr,
-                           "lseek(%s, %llu): %s\n",
-                           e->name, e->pos, strerror(errno));
-
-               /* Sleep for a slight random delay */
-               (void) usleep(random() % 1000);
-
-               /* Reseed PRNG out of /dev/urandom periodically */
-               prng_reseed();
-       }
-
-       ret = EXIT_SUCCESS;
-       /* FALLTHROUGH */
-
-end:
-       /* Cleanup */
-       if (readbuf != NULL)
-               buffer_free(readbuf, BLOCK_SIZE * BLOCK_MULTIPLE);
-       (void) unlink(pidfile);
-       disks_close();
-       prng_close();
-
-       return ret;
-}
-
-/*
- * Seed 4.2BSD random(3) using rnd(4)'s /dev/urandom
- */
-static int
-prng_init(void)
-{
-       unsigned long   seed;
-
-       if ((urandom = open("/dev/urandom", O_RDONLY)) == -1) {
-               (void) fprintf(stderr,
-                   "open(/dev/urandom): %s\n", strerror(errno));
-               goto err;
-       }
-       if (read(urandom, &seed, sizeof(seed)) != sizeof(seed)) {
-               (void) fprintf(stderr,
-                   "read(/dev/urandom): %s\n", strerror(errno));
-               goto err;
-       }
-
-       srandom(seed);
-       reseed = RESEED_MIN + (random() % (RESEED_MAX - RESEED_MIN));
-
-       return 0;
-
-err:
-       if (urandom != -1) {
-               (void) close(urandom);
-               urandom = -1;
-       }
-
-       return -1;
-}
-
-static void
-prng_reseed(void)
-{
-       unsigned long   seed;
-
-       if (--reseed < 1) {
-               if (read(urandom, &seed, sizeof(seed)) != sizeof(seed)) {
-                       (void) fprintf(stderr,
-                           "read(/dev/urandom): %s\n", strerror(errno));
-               }
-               srandom(seed);
-               reseed = RESEED_MIN + (random() % (RESEED_MAX - RESEED_MIN));
-       }
-}
-
-static void
-prng_close(void)
-{
-
-       if (urandom != -1) {
-               (void) close(urandom);
-               urandom = -1;
-       }
-}
-
-/*
- * Called upon reception of SIGTERM
- */
-static void
-signal_handler(int sig)
-{
-
-       switch (sig) {
-       case SIGTERM:   /* FALLTHROUGH */
-       default:
-               run = 0;
-       }
-}
-
-/*
- * Become a background daemon and write our PID file.
- * Returns 0 on success or -1 on error.
- */
-static int
-detach(const char *pidfile)
-{
-       pid_t                   pid;
-       int                     fd;
-       struct sigaction        act;
-
-       if ((pid = fork()) == -1)
-               return -1;
-       if (pid != 0)
-               exit(EXIT_SUCCESS);
-
-       /* Create PID file */
-       if ((fd = open(pidfile, O_CREAT | O_TRUNC | O_WRONLY, 0600)) != -1) {
-               char    str[16];
-
-               (void) snprintf(str, 15, "%d\n", getpid());
-               if (write(fd, str, strlen(str)) == -1 || close(fd) == -1) {
-                       (void) fprintf(stderr,
-                           "Error writing PID file [%s]: %s\n",
-                           pidfile, strerror(errno));
-                       return -1;
-               }
-       } else {
-               (void) fprintf(stderr,
-                   "Error creating PID file [%s]: %s\n",
-                   pidfile, strerror(errno));
-               return -1;
-       }
-
-       /* Be paranoid, redirect our stdio file descriptors to null(4) */
-       (void) setsid();
-       (void) chdir("/");
-       if ((fd = open("/dev/null", O_RDWR)) != -1) {
-               (void) dup2(fd, STDIN_FILENO);
-               (void) dup2(fd, STDOUT_FILENO);
-               /* Keep stderr */
-               if (fd > STDERR_FILENO)
-                       (void) close(fd);
-       }
-
-       /* Set our SIGTERM handler and ignore some signals */
-       act.sa_handler = signal_handler;
-       act.sa_flags = 0;
-       (void) sigemptyset(&act.sa_mask);
-       (void) sigaction(SIGTERM, &act, NULL);
-       act.sa_handler = SIG_IGN;
-       (void) sigaction(SIGTTOU, &act, NULL);
-       (void) sigaction(SIGTTIN, &act, NULL);
-       (void) sigaction(SIGTSTP, &act, NULL);
-
-       return 0;
-}
-
-/*
- * Attempts to open specified disk device and on success adds a new disk_t
- * entry to the disks_list.  Logs any errors to stderr.
- */
-static void
-disk_open(const char *dname)
-{
-       disk_t  *e;
-       char    devname[16];
-
-       if ((e = malloc(sizeof(disk_t))) == NULL) {
-               (void) fprintf(stderr,
-                   "malloc(%d): %s\n", sizeof(disk_t), strerror(errno));
-               goto err;
-       }
-       if ((e->name = strdup(dname)) == NULL) {
-               (void) fprintf(stderr,
-                   "strdup(%d): %s\n", strlen(dname), strerror(errno));
-               goto err;
-       }
-
-       (void) snprintf(devname, 16, "/dev/r%sd", dname);
-       if ((e->fd = open(devname, O_RDONLY)) == -1) {
-               (void) fprintf(stderr,
-                   "open(%s): %s\n", devname, strerror(errno));
-               goto err;
-       }
-
-       /*
-        * Although we could use an ioctl(2) to read the label of the device,
-        * using lseek(2) is simpler.  If it generates head movement, it's all
-        * for the better.
-        */
-       if (lseek(e->fd, 0, SEEK_END) == -1) {
-               (void) fprintf(stderr,
-                   "lseek(%s): %s\n", devname, strerror(errno));
-               goto err;
-       }
-       if ((e->max = lseek(e->fd, 0, SEEK_SET)) == -1) {
-               (void) fprintf(stderr,
-                   "lseek(%s): %s\n", devname, strerror(errno));
-               goto err;
-       }
-       /*
-        * Substract so that any position is valid for reading up to
-        * BLOCK_SIZE * BLOCK_MULTIPLE bytes.  We also ensure that size
-        * is always a multiple of BLOCK_SIZE.
-        */
-       e->max = BALIGN_CEIL(e->max - (BLOCK_SIZE * BLOCK_MULTIPLE),
-           BLOCK_SIZE);
-
-       /* Set a random but valid start position, BLOCK_SIZE aligned. */
-       e->pos = BALIGN_CEIL(((off_t)random() * (off_t)random()) %
-           (e->max + 1), BLOCK_SIZE);
-
-       /* And a random direction/count */
-       e->dir = random() % 2;
-       e->dircnt = DIRECTION_MIN +
-           (random() % (DIRECTION_MAX - DIRECTION_MIN));
-
-       SLIST_INSERT_HEAD(&disks_list, e, chain);
-       ndisks++;
-       return;
-
-err:
-       if (e != NULL) {
-               if (e->name != NULL)
-                       free(e->name);
-               if (e->fd != -1)
-                       (void) close(e->fd);
-               free(e);
-       }
-}
-
-/*
- * Queries sysctl(3) for wd* and sd* drive names and opens the devices.
- * Returns 0 on success or -1 on failure.
- */
-static int
-disks_open(void)
-{
-       int     mib[] = { CTL_HW, HW_DISKNAMES };
-       char    buf[1024], *cptr, *sptr;
-       size_t  size = sizeof(buf);
-
-       /* Query local disks */
-       if (sysctl(mib, 2, buf, &size, NULL, 0) != 0) {
-               (void) fprintf(stderr,
-                   "Error querying sysctl(3) for disk names: %s\n",
-                   strerror(errno));
-               goto err;
-       }
-
-       /* Open for each sd(4) or wd(4) disk reported, up to maxdisks */
-       /* XXX We actually could use strsep(3) easily here as well */
-       for (cptr = buf, ndisks = 0; ndisks < maxdisks; ) {
-               for (; *cptr != '\0' && *cptr == ' '; cptr++) ;
-               if (*cptr == '\0')
-                       break;
-               sptr = cptr;
-               for (; *cptr != '\0' && *cptr != ' '; cptr++) ;
-               if (*cptr == '\0')
-                       break;
-               *cptr++ = '\0';
-               if ((sptr[0] == 's' || sptr[0] == 'w') &&
-                   sptr[1] == 'd')
-                       disk_open(sptr);
-       }
-
-       if (ndisks == 0) {
-               (void) fprintf(stderr,
-                   "No sd(4) or wd(4) disks to generate entropy from\n");
-               goto err;
-       }
-
-       /* Initialize fast index array */
-       if ((disks_array = malloc(sizeof(disk_t *) * ndisks)) == NULL) {
-               (void) fprintf(stderr,
-                   "malloc(%d): %s\n", sizeof(disk_t *) * ndisks,
-                   strerror(errno));
-               goto err;
-       }
-       {
-               int     i = 0;
-               disk_t  *e;
-
-               SLIST_FOREACH(e, &disks_list, chain)
-                       disks_array[i++] = e;
-       }
-
-       return 0;
-
-err:
-       disks_close();
-
-       return -1;
-}
-
-/*
- * Closes any open drive devices if any.
- */
-static void
-disks_close(void)
-{
-       disk_t  *e;
-
-       if (disks_array != NULL)
-               free(disks_array);
-
-       while (!SLIST_EMPTY(&disks_list)) {
-               e = SLIST_FIRST(&disks_list);
-               SLIST_REMOVE_HEAD(&disks_list, chain);
-               if (e->fd != -1)
-                       (void) close(e->fd);
-               if (e->name != NULL)
-                       free(e->name);
-               free(e);
-       }
-
-       ndisks = 0;
-}
-
-/*
- * Allocate a wired memory buffer.
- */
-static void *
-buffer_alloc(size_t size)
-{
-       void    *buf = NULL;
-
-       if (pagesize == 0) {
-               if ((pagesize = (size_t)sysconf(_SC_PAGESIZE)) == -1) {
-                       perror("sysconf(_SC_PAGESIZE)");
-                       goto err;
-               }
-       }
-
-       size = (size_t)BALIGN_CEIL(size, pagesize);
-
-       if ((buf = mmap(NULL, size, PROT_WRITE, MAP_ANON, -1, 0)) ==
-           MAP_FAILED) {
-               (void) fprintf(stderr,
-                   "mmap(%d): %s\n", size, strerror(errno));
-               buf = NULL;
-               goto err;
-       }
-       if (mlock(buf, size) == -1) {
-               perror("mlock()");
-               goto err;
-       }
-       if (madvise(buf, size, MADV_SEQUENTIAL) == -1) {
-               perror("madvise()");
-               goto err;
-       }
-
-       return buf;
-
-err:
-       if (buf != NULL) {
-               (void) munlock(buf, size);
-               (void) munmap(buf, size);
-       }
-
-       return NULL;
-}
-
-/*
- * Free a previously allocated wired buffer.
- */
-static void
-buffer_free(void *buf, size_t size)
-{
-
-       assert(pagesize != 0 && buf != NULL);
-
-       size = (size_t)BALIGN_CEIL(size, pagesize);
-
-       (void) memset(buf, 0, size);
-       (void) munlock(buf, size);
-       (void) munmap(buf, size);
-}
diff --git a/tests/js-test/README b/tests/js-test/README
deleted file mode 100644 (file)
index 5922bc8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-$Id: README,v 1.3 2006/07/22 04:47:43 mmondor Exp $
-
-Note that this was a test tree only.  The current code which is in use
-can be found under /cvsroot/mmondor/mmsoftware/js/
-
-Thanks,
-Matt
diff --git a/tests/js-test/js/copy.js b/tests/js-test/js/copy.js
deleted file mode 100644 (file)
index 49dcc82..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* $Id: copy.js,v 1.2 2005/07/01 13:11:08 mmondor Exp $ */
-
-/*
- * Test our read() and write() methods, mapping to unix read(2) and write(2).
- * Seems to be working great so far.
- */
-
-src = '/tmp/src.bin'
-dst = '/tmp/dst.bin'
-
-err = new FD();
-err.set(FD.STDERR_FILENO);
-
-srcfd = new FD();
-dstfd = new FD();
-
-try {
-       srcfd.open(src, FD.O_RDONLY);
-       dstfd.open(dst, FD.O_WRONLY | FD.O_CREAT);
-
-       var data;
-
-       while (data = srcfd.read(16384)) {
-               if (data.length == 0)
-                       break;
-               err.put('Copied ' + data.length + " bytes block\n");
-               dstfd.write(data);
-       }
-
-       srcfd.close();
-       dstfd.fdatasync();
-       dstfd.close();
-} catch (x) {
-       err.put(x + "\n");
-}
-
-err.close();
diff --git a/tests/js-test/js/fd.js b/tests/js-test/js/fd.js
deleted file mode 100644 (file)
index 8e8f998..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* $Id: fd.js,v 1.5 2005/02/10 10:34:25 mmondor Exp $ */
-
-var out = new FD();
-out.set(FD.STDOUT_FILENO);
-
-try {
-
-       var fd = new FD();
-
-       {
-               var size;
-
-               fd.open("/tmp/test.txt", FD.O_WRONLY | FD.O_CREAT);
-               size = fd.put("Yo!\n");
-               out.put('Wrote bytes=' + size + ' to file="' + fd.path +
-                   '", fd=' + fd.fd + ', created with mode=' + fd.mode +
-                   "\n");
-               fd.close();
-       }
-
-       {
-               var buf;
-
-               fd.open("/tmp/test.txt", FD.O_RDONLY);
-               while (buf = fd.get())
-                       out.put(buf);
-               fd.close();
-       }
-
-} catch (x) {
-       out.put(x + "\n");
-}
-
-out.put("done\n");
-out.close();
diff --git a/tests/js-test/js/game/objects.js b/tests/js-test/js/game/objects.js
deleted file mode 100644 (file)
index 96fdfe7..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-/* $Id: objects.js,v 1.7 2005/11/25 07:38:35 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Primarily written in JavaScript for easy and quick prototyping/testing.
- * May eventually be written in C afterwards if need be, but the game might
- * actually be implemented in JavaScript too depending on future decisions.
- */
-
-/*
- * Simple but rather realistic implementation of items and containers.
- * We observe containers maximum allowed volume and weight, container neck
- * size, as well as expandable containers, such as cloth bags which can expand
- * to eventually fill their parent container too.  We allow nestled
- * containers.  We also add the concept of arbitrary marks which a user might
- * add to objects to differenciate them.  Containers can be open or closed,
- * and obviously need to be open for items to be added/removed from them.
- * We flag containers as such to accept either only solids or liquids, or
- * both.  We could consider flowing sand or salt as a liquid in this case.
- *
- * XXX
- * - For liquids, we might need to provide a special object or flag for them
- *   to be able to have a volume/weight ratio, so that we could perform
- *   actions easily such as fill bottles/bags, etc.
- * - The code dealing with the container parents, weights and expanding volume
- *   containers needs to throughly be tested, both for success and failing
- *   cases of all kinds.
- * - XXX FIXME XXX
- *   When removing items from a container, the container's weight becomes 0,
- *   as well as its volume if it is expandable.
- */
-
-
-
-/*
- * Describes a game item or object.
- */
-
-/* Used so that every item has a unique index ID */
-var unique             = 0;
-
-/* Content types */
-const CT_SOLID         = (1 << 0);
-const CT_LIQUID                = (1 << 1);
-/* And container type flag */
-const CT_EXPAND                = (1 << 2);
-/* If item cannot be taken */
-const CT_FIXED         = (1 << 3);
-
-function Item(name, description, volume, weight, ctype)
-{
-       this.name = name;
-       this.description = description;
-       this.volume = volume;
-       this.weight = weight;
-       this.ctype = ctype;
-
-       this.marks = [];
-
-       this.index = ++unique;
-}
-
-Item.prototype = {
-       isContainer: function()
-       {
-               return false;
-       },
-
-       getVolume: function()
-       {
-               return this.volume;
-       },
-
-       getWeight: function()
-       {
-               return this.weight;
-       },
-
-       mark: function(mark)
-       {
-               this.mark.push(mark);
-       }
-};
-
-
-/*
- * And an object to handle container Items, inheriting the Item object.
- */
-
-const E_OK             = 0;
-const E_TOOLARGE       = "Item too large";
-const E_TOOHEAVY       = "Item too heavy";
-const E_FIXED          = "Item is well fixed and cannot move";
-const E_BADTYPE                = "Item is not of proper type (solid vs liquid)";
-const E_SELF           = "Item could not penetrate itself";
-const E_NONE           = "Item not in container";
-const E_ALREADY                = "Item already in container";
-const E_CLOSED         = "Container is closed";
-
-function ContainerItem(name, description, volume, weight, ctype,
-    con_neck, con_volume_max, con_weight_max, con_ctype)
-{
-       this.base = Item;
-       this.base(name, description, volume, weight, ctype);
-
-       this.con_neck = con_neck;
-       this.con_volume_max = con_volume_max;
-       this.con_weight_max = con_weight_max;
-       this.con_volume_cur = this.con_weight_cur = 0;
-       this.con_ctype = con_ctype;
-
-       this.con_items = {};
-       this.con_items_cnt = 0;
-       this.con_open = false;
-}
-
-ContainerItem.prototype = {
-       isContainer: function()
-       {
-               return true;
-       },
-
-       open: function()
-       {
-               this.con_open = true;
-       },
-
-       close: function()
-       {
-               this.con_open = false;
-       },
-
-       getVolume: function()
-       {
-               /*
-                * Objects which expand, such as bags, need to report proper
-                * volume relating to the volume of the objects they hold.
-                * Objects which do not expand, such as boxes or bottles,
-                * need to always report the same volume.
-                */
-               return ((this.con_ctype & CT_EXPAND) != 0) ?
-                   this.volume + this.con_volume_cur :
-                   this.volume;
-       },
-
-       getWeight: function()
-       {
-               return this.weight + this.con_weight_cur;
-       },
-
-       items: function()
-       {
-               return this.con_items_cnt;
-       },
-
-       add: function(item)
-       {
-               /* We can't accept fixed items */
-               if ((item.ctype & CT_FIXED) != 0)
-                       return E_FIXED;
-
-               /* Can only add items to open container */
-               if (!this.con_open)
-                       return E_CLOSED;
-
-               /* We can't add ourself in :) */
-               if (item.index == this.index)
-                       return E_SELF;
-
-               /* Nor items which are already inside */
-               if (this.con_items[item.index] != undefined)
-                       return E_ALREADY;
-
-               /* We only accept items of proper type */
-               if ((this.con_ctype & item.ctype) == 0)
-                       return E_BADTYPE;
-
-               /* We can only hold objects which are small enough */
-               if (this.con_neck < item.getVolume())
-                       return E_TOOLARGE;
-               if (this.con_volume_cur + item.getVolume() >
-                   this.con_volume_max)
-                       return E_TOOLARGE;
-
-               /* We can only hold objects which are light enough */
-               if (this.con_weight_cur + item.getWeight() >
-                   this.con_weight_max)
-                       return E_TOOHEAVY;
-
-               this.con_volume_cur += item.getVolume();
-               this.con_weight_cur += item.getWeight();
-
-               /*
-                * The weight has to propagate to parent containers.
-                * The volume also has, in the case where containers
-                * are expandable.
-                * We need to observe the maximum allowed volume and weight
-                * of all parent containers as well.
-                * We need to climb through the parents list to do this.
-                * Moreover, we need to actually reverse any changes made
-                * to the parents in case of any volume/weight exceeded.
-                */
-               var err = E_OK;
-               for (var o = this.con_parent; o != undefined;
-                   o = o.con_parent) {
-                       if (o.getWeight() + this.getWeight() >
-                           o.con_weight_max) {
-                               err = E_TOOHEAVY;
-                               break;
-                       }
-                       o.con_weight_cur += this.getWeight();
-                       if ((o.con_ctype & CT_EXPAND) != 0) {
-                               if (o.getVolume() + this.getVolume() >
-                                   o.con_volume_max) {
-                                       err = E_TOOLARGE;
-                                       break;
-                               }
-                               o.con_volume_cur += this.getVolume();
-                       }
-               }
-               if (err != E_OK) {
-                       for (var t = this.con_parent; t != o;
-                           t = t.con_parent) {
-                               t.con_weight -= this.getWeight();
-                               if ((t.con_ctype & CT_EXPAND) != 0)
-                                       t.con_volume_cur -= this.getVolume();
-                       }
-                       if (err == E_TOOLARGE)
-                               o.con_weight_cur -= this.getWeight();
-
-                       this.con_volume_cur -= item.getVolume();
-                       this.con_weight_cur -= item.getWeight();
-
-                       return err;
-               }
-
-               if (item.isContainer())
-                       item.con_parent = this;
-               this.con_items[item.index] = item;
-               this.con_items_cnt++;
-
-               return E_OK;
-       },
-
-       remove: function(item)
-       {
-               /* Can only remove items from open container */
-               if (!this.con_open)
-                       return E_CLOSED;
-
-               /* We can only remove items which are really inside */
-               if (this.con_items[item.index] == undefined)
-                       return E_NONE;
-
-               /*
-                * Climb up our parents containers list to update them
-                */
-               for (var o = this.con_parent; o != undefined;
-                   o = o.con_parent) {
-                       o.con_weight_cur -= this.getWeight();
-                       if ((o.con_ctype & CT_EXPAND) != 0)
-                               o.con_volume_cur -= this.getVolume();
-               }
-
-               if (item.isContainer())
-                       delete item.con_parent;
-               this.con_weight_cur -= item.getWeight();
-               this.con_volume_cur -= item.getVolume();
-               delete this.con_items[item.index];
-               this.con_items_cnt--;
-
-               return E_OK;
-       },
-
-       inventory: function(level)
-       {
-               print(' - ' + level +
-                   ': name=' + this.name +
-                   ' volume=' + this.getVolume() +
-                   ' weight=' + this.getWeight());
-
-               if (!this.con_open)
-                       return 'already_open!';
-
-               level++;
-               for (var i in this.con_items) {
-                       /*
-                       if (this.con_items[i] == undefined)
-                               continue;
-                        */
-                       print(level +
-                           ': name=' + this.con_items[i].name +
-                           ' volume=' + this.con_items[i].getVolume() +
-                           ' weight=' + this.con_items[i].getWeight());
-                       if (this.con_items[i].isContainer())
-                               this.con_items[i].inventory(level);
-               }
-               level--;
-       }
-};
-
-
-
-/*
- * Some testing in order
- */
-
-/* Create an item */
-var i = new Item('a ring', 'the one ring', 5, 5, CT_SOLID);
-
-/* Create a container item */
-var c = new ContainerItem('a bag', 'a soft cloth bag', 5, 5, CT_SOLID,
-    10, 15, 20, CT_SOLID | CT_EXPAND);
-
-/* Create a second container item */
-var c2 = new ContainerItem('another bag', 'another soft cloth bag', 5, 5,
-    CT_SOLID, 10, 15, 20, CT_SOLID | CT_EXPAND);
-
-print();
-c2.inventory(0);
-print();
-
-c.open();
-print(c.add(i));
-c.close();
-c2.open();
-print(c2.add(c));
-c2.close();
-
-c.open();
-c2.open();
-c2.inventory(0);
-c.remove(i);
-c2.remove(c);
-
-print();
-c2.inventory(0);
diff --git a/tests/js-test/js/httpd/httpd.js b/tests/js-test/js/httpd/httpd.js
deleted file mode 100644 (file)
index 0b24dac..0000000
+++ /dev/null
@@ -1,1679 +0,0 @@
-/* $Id: httpd.js,v 1.74 2005/12/17 00:13:12 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Little example showing the versatility of ECMAScript, provided with a
- * custom library for BSD socket support, using SpiderMonkey.
- * This tiny HTTPd allows simultaneous concurrent client connections without
- * using multiple threads or processes.  Must be ran through
- * ../../src/js-server.
- *
- * Configuration options can be found in options.js
- *
- * XXX Possibly that with close var semantics changes or such, we could
- * support Keep-Alive for HTTP/1.1 connections.  This however is not a
- * priority at current time.
- *
- * TODO:
- * - There is a problem if the remote socket closes when we're sending
- *   alot of data, poll(2) apparently doesn't always save us from this
- *   despite checking POLLHUP/POLLERR events.  A SIGPIPE signal is sent
- *   to the process, and we must be able to handle some common signals.
- *   This would also allow an opportunity for applications to register
- *   server cleanup handlers when SIGTERM is received, i.e. to save to
- *   disk in-memory cached data, etc.
- *   We probably should ensure to block the signal when executing the
- *   user function for an occurred signal...
- * - Read http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
- *   and see if we meet conformance, adjust as needed.
- * - We might want to check Accept-Language: for multilingual sites...
- * - See what to do for HEAD and PUT
- * - Possibly limit rate of connections per address like I did in
- *   mmftpd/mmsmtpd/mmpop3d/mmspawnd, a requested feature of 3s4i.
- *   If enabling this, it probably should be per-vhost configurable.
- *   I'm not sure HTTP protocol is well suited to this type of limiting,
- *   some testing will be required.
- * - Provide a function to scripts to redirect to another page.
- * - We might want vhost-specific default login page, and provide
- *   an easy means in the server to have non-authenticated users automatically
- *   redirected to that page using server-side magic.  A special session
- *   variable should be used for this, and registered when the user logins.
- * - Similar to the above, but should be special provision for scripts to
- *   easily specify their required access level, which must be met by a
- *   currently logged in user, which is otherwise redirected to an
- *   application-specific page.
- * - Implement logging
- * - It might be nice to implement a minimal database-like facility, where
- *   for performance we could log changes, and only sync to disk once in a
- *   while, discarding obsolete logs...  JSON would be used
- * - Enhance the JS shell to report errors better
- * - We should have support for easy storage and safe export of files,
- *   like I implemented for ascpi.com.  This is useful for instance to
- *   store and post user profile images and related thumbnail, etc.
- */
-
-
-
-/*
- * Server identification
- */
-SERVER_VERSION                 = 'mmondor_js_httpd/0.0.1 (NetBSD)';
-SERVER_CVSID   = '$Id: httpd.js,v 1.74 2005/12/17 00:13:12 mmondor Exp $';
-
-
-
-/*
- * Open standard error FD for diagnostics output
- */
-err = new FD();
-err.set(FD.STDERR_FILENO);
-
-
-
-/*
- * Import needed functionality from external modules, since #include is
- * missing :)
- */
-function file_read(file)
-{
-       var contents = '';
-       var data;
-       var fd;
-
-       try {
-               /*
-                * If we were provided with a filename, rather than a
-                * filedescriptor object, open the filename.  Otherwise,
-                * read from the specified FD.
-                */
-               if (typeof file != 'object') {
-                       fd = new FD();
-                       fd.open(file, FD.O_RDONLY);
-               } else
-                       fd = file;
-       } catch (x) {
-               err.put(x + " at file_read()\n");
-       }
-
-       try {
-               for (;;) {
-                       data = fd.read(65536);
-                       if (data.length == 0)
-                               break;
-                       contents += data;
-               }
-       } catch (x) {
-               err.put(x + " at file_read()\n");
-       }
-
-       fd.close();
-
-       return contents;
-}
-
-try {
-       eval(file_read('options.js'));          /* Configuration */
-} catch (x) {
-       err.put(x + " while reading options file\n");
-       exit();
-}
-eval(file_read('string.js'));          /* startsWith()/endsWith() */
-eval(file_read('ml.js'));              /* MLTag object for HTML generation */
-eval(file_read('root.js'));            /* Root object for virtual chroot(2) */
-
-
-
-/*
- * Client states (enumeration)
- */
-const STATE_TRANSFER_READ      = 1;
-const STATE_TRANSFER_WRITE     = 2;
-
-
-
-/*
- * Quick lookup object from virtual hosts names and aliases to VHost objects
- */
-var vhosts_table = {};
-var default_vhost = undefined;
-
-/*
- * The VHost object
- */
-function VHost(o)
-{
-       /*
-        * A few properties are definitely required
-        */
-       if (o.name == undefined || o.root == undefined)
-               throw ('name and root properties missing from vhost');
-       o.name = o.name.toLowerCase();
-       this.name = o.name;
-
-       if (o.scripts != undefined && o.scripts == true) {
-               this.scripts = true;
-               this.globals = {};
-       }
-
-       /*
-        * Create VHost object
-        */
-       try {
-               this.htdocs_root = new Root(o.root);
-       } catch (x) {
-               throw (x);
-       }
-
-       if (o.charset != undefined)
-               this.charset = o.charset;
-       if (o.session_exp != undefined)
-               this.session_exp = o.session_exp;
-
-       /*
-        * Link object to vhosts table
-        */
-       if (vhosts_table[o.name] != undefined)
-               throw ('Conflicting vhost name: ' + o.name);
-       vhosts_table[o.name] = this;
-
-       if (o.aliases != undefined) {
-               for (i in o.aliases) {
-                       o.aliases[i] = o.aliases[i].toLowerCase();
-                       if (vhosts_table[o.aliases[i]] != undefined)
-                               throw ('Conflicting vhost alias: ' +
-                                   o.aliases[i]);
-                       vhosts_table[o.aliases[i]] = this;
-               }
-       }
-}
-
-
-
-/*
- * The Session object allows to maintain persistent session variables among
- * multiple client queries.  We are using a cookie with the unique session ID
- * to link those queries together into a session.
- */
-
-var o = new FD();
-o.set(FD.STDOUT_FILENO);
-
-var session_randfd = new FD();
-try {
-       session_randfd.open('/dev/urandom', FD.O_RDONLY);
-} catch (x) {
-       err.put(x + " while attempting to open /dev/urandom\n");
-       exit();
-}
-
-var session_charlist = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
-                       'abcdefghijklmnopqrstuvwxyz' +
-                       '0123456789-_';
-
-var sessions_table = {};
-
-/*
- * To be called at regular but spaced intervals,
- * destroys expired session objects.
- */
-function session_gc(time)
-{
-       var i;
-
-       for (i in sessions_table) {
-               if (sessions_table[i].expires <= time)
-                       delete sessions_table[i];
-       }
-}
-
-function Session(time, exp)
-{
-       var rval;
-       var i;
-
-       try {
-               rval = session_randfd.read(options.sess_id_size);
-       } catch (x) {
-               err.put(x + " while attempting to read from /dev/urandom\n");
-       }
-       this.sessid = '';
-       for (i = 0; i < options.sess_id_size; i++)
-               this.sessid +=
-                   session_charlist.charAt(rval.charCodeAt(i) & 0x3f);
-
-       this.variables = {};
-       this.expires = time + exp;
-       sessions_table[this.sessid] = this;
-}
-
-
-
-/*
- * For the mime types database
- */
-
-var mimetypes_table = {};
-
-
-
-/*
- * And our pre-evaluated scripts cache
- */
-var jso_cache = {};
-
-function JSO(path, time, script)
-{
-       this.path = path;
-       this.time = time;
-       this.script = script;
-
-       jso_cache[this.path] = this;
-}
-
-
-
-/*
- * The HTTPReply object allows to cache addHeader() and addContent() requests,
- * and to eventually flush the whole reply to an arbitrary FD afterwards.
- */
-
-/*
- * Constructor
- */
-function HTTPReply(code, desc, type)
-{
-       this.code = code;
-       this.desc = desc;
-       this.headers = [];
-       this.contents = [];
-       this.type = type;
-
-       /*
-        * Insert our standard headers.
-        */
-       this.gmttime = (new Date()).toGMTString();
-       this.headers.push('Date: ' + this.gmttime);
-       this.headers.push('Server: ' + SERVER_VERSION);
-       this.headers.push('Connection: close');
-       this.headers.push('Accept-Ranges: bytes');
-}
-/*
- * HTTPReply prototype object
- */
-HTTPReply.prototype = {
-       setType: function(type)
-       {
-
-               this.type = type;
-       },
-
-       addHeader: function(data)
-       {
-
-               this.headers.push(data);
-       },
-
-       addNoCacheHeaders: function()
-       {
-
-               this.headers.push('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
-               this.headers.push('Last-Modified: ' + this.gmttime);
-               this.headers.push('Cache-Control: no-cache, must-revalidate');
-               this.headers.push('Pragma: no-cache');
-       },
-
-       addContent: function(data)
-       {
-
-               this.contents.push(data);
-       },
-
-       flush: function(fd, size)
-       {
-               var headers = '';
-               var contents = '';
-               var i;
-
-               for (i = 0; i < this.contents.length; i++)
-                       contents += this.contents[i];
-
-               this.headers.push('Content-Length: ' +
-                   (size == null ? contents.length : size));
-               headers += 'HTTP/1.1 ' + this.code + ' ' + this.desc + "\r\n";
-               for (i = 0; i < this.headers.length; i++)
-                       headers += this.headers[i] + "\r\n";
-               if (this.type != null)
-                       headers += 'Content-Type: ' + this.type + "\r\n";
-               headers += "\r\n";
-
-               try {
-                       if (!fd.http_old_get)
-                               fd.bwrite(headers + contents);
-                       else
-                               fd.bwrite(contents);
-               } catch (x) {}
-       }
-}
-
-/*
- * Generates an error page and sends it to specified FD object.
- */
-function http_error(fd, code, desc, ldesc)
-{
-       var res = new HTTPReply(code, desc, 'text/html; charset=' +
-           options.default_charset);
-       res.addNoCacheHeaders();
-
-       res.addContent('<html><head><title>' + code + ' ' + desc +
-           '</title></head><body><h1>' + code + ' ' + desc + '</h1>' +
-           '<p>' + ldesc + '</p><br>');
-
-       res.addContent(fd.httpDebug());
-
-       res.addContent('<br><sub>' + SERVER_VERSION + '<br>' + SERVER_CVSID +
-           '</sub></body></html>');
-
-       res.flush(fd, null);
-       delete res;
-}
-
-
-
-/*
- * Add new methods to the FD prototype object (JavaScript is great like that).
- * We need to add these properties one by one to the prototype object of FD,
- * since we wouldn't want to override its default prototype, just expand it.
- */
-
-/*
- * Handles request query processing, to be assigned to FD.process() while in
- * the request query state.  This then invokes parseRequest() which may
- * either send an HTTP response and/or cause a switch to another state.
- */
-function process_query(time)
-{
-       var len;
-       var done = false;
-       var close = false;
-       var idx;
-       var data;
-
-       /*
-        * If we reach a request of 32768 bytes, stop reading.
-        * If there is no request terminating line within
-        * that buffer, close connection.
-        *
-        * On read error, close connection.
-        *
-        * If we do find request terminating line, parse query
-        * to modify state accordingly, and let the parsing
-        * method decide if we'll close the connection.
-        */
-       len = 32768 - this.request_data.length;
-       if (len < 1) {
-               done = true;
-               close = true;
-       } else {
-               try {
-                       data = this.read(len);
-                       if (data.length == 0)
-                               close = true;
-                       this.request_data += data;
-                       this.updateTimeout(time);
-               } catch (x) {
-                       if (this.errno != Errno.EAGAIN)
-                               close = true;
-               }
-       }
-       if ((idx = this.request_data.indexOf("\r\n\r\n")) != -1)
-               done = true;
-       else if (!this.checked_old &&
-           (idx = this.request_data.indexOf("\r\n")) != -1) {
-               var w;
-
-               this.checked_old = true;
-               if ((w = (this.request_data.substr(0, idx)).split(' ')).
-                   length == 2 && w[0] == 'GET') {
-                       /*
-                        * Old-style HTTP request, we need to respond
-                        * immediately in this case without any headers.
-                        */
-                       done = true;
-               }
-       }
-
-       if (done && !close) {
-               /*
-                * Store remaining of buffer after "\r\n" so that we may
-                * be able to process POST for instance, without needing
-                * to read one char at a time here.
-                * Then call our request parsing function.
-                */
-               idx += 4;
-               this.bread_buffer = this.request_data.substr(idx);
-               this.request_data = this.request_data.substr(0, idx);
-               close = this.parseRequest(time);
-       }
-
-       return close;
-}
-
-function process_post(time)
-{
-       var close = false;
-       var len;
-       var data;
-
-       if (this.post_data.length < this.http_content_length) {
-               len = this.http_content_length - this.post_data.length;
-               if (len > options.readbuf_size)
-                       len = options.readbuf_size;
-               try {
-                       data = this.read(len);
-                       if (data.length == 0)
-                               close = true;
-                       this.post_data += data;
-                       this.updateTimeout(time);
-               } catch (x) {
-                       if (this.errno != Errno.EAGAIN)
-                               close = true;
-               }
-       } else
-               close = this.parsePost(time);
-
-       return close;
-}
-
-/*
- * Handles transfer processing, to be assigned to FD.process() while in the
- * transfer state.
- */
-function process_transfer(time)
-{
-       var close = false;
-
-       /*
-        * STATE_TRANSFER_READ specifies that we're reading to the
-        * buffer from transfer_src, or writing from the buffer
-        * to transfer_dst (STATE_TRANSFER_WRITE).  We can do
-        * both steps one after another if possible.
-        * On EAGAIN errors, simply pass our turn to go back to
-        * polling.  On EOF reading from either end, exit transfer
-        * state after writing to the other and syncing/closing,
-        * and order to close client descriptor.
-        * We take care not to transfer more than this.transfer_size bytes
-        * outbound.
-        * XXX We might also want to observe it for inbound, where it could
-        * be set to the user-provided Content-Length...  for PUT ?
-        */
-       if (this.transfer_state == STATE_TRANSFER_READ) {
-               if (this == this.transfer_src) {
-                       /* Reading from client */
-                       try {
-                               this.transfer_data =
-                                   this.read(options.readbuf_size);
-                               if (this.transfer_data.length == 0)
-                                       this.transfer_eof = true;
-                               this.transfer_state = STATE_TRANSFER_WRITE;
-                               this.updateTimeout(time);
-                       } catch (x) {
-                               if (this.errno != Errno.EAGAIN) {
-                                       close = true;
-                                       try {
-                                               this.transfer_dst.fdatasync();
-                                       } catch (x) {}
-                                       try {
-                                               this.transfer_dst.close();
-                                       } catch (x) {}
-                               }
-                       }
-               } else {
-                       /* Reading from file */
-                       var bufsiz = this.transfer_size;
-                       if (bufsiz > options.readbuf_size)
-                               bufsiz = options.readbuf_size;
-                       try {
-                               if (bufsiz > 0)
-                                       this.transfer_data =
-                                           this.transfer_src.read(bufsiz);
-                               else
-                                       this.transfer_data = '';
-                               if (this.transfer_data.length == 0)
-                                       this.transfer_eof = true;
-                               this.transfer_size -=
-                                   this.transfer_data.length;
-                               this.transfer_state = STATE_TRANSFER_WRITE;
-                       } catch (x) {
-                               close = true;
-                               try {
-                                       this.transfer_src.close();
-                               } catch (x) {}
-                       }
-               }
-       }
-       if (this.transfer_state == STATE_TRANSFER_WRITE) {
-               if (this == this.transfer_dst) {
-                       /* Writing to client */
-                       if (this.transfer_eof)
-                               close = true;
-                       else {
-                               try {
-                                       this.bwrite(this.transfer_data);
-                                       this.transfer_state =
-                                           STATE_TRANSFER_READ;
-                                       this.updateTimeout(time);
-                               } catch (x) {
-                                       if (this.errno != Errno.EAGAIN)
-                                               close = true;
-                               }
-                       }
-                       if (close) {
-                               try {
-                                       this.transfer_src.close();
-                               } catch (x) {}
-                       }
-               } else {
-                       /* Writing to file */
-                       if (this.transfer_eof)
-                               close = true;
-                       else {
-                               try {
-                                       this.transfer_dst.write(
-                                           this.transfer_data);
-                                       this.transfer_state =
-                                           STAT_TRANSFER_READ;
-                               } catch (x) {
-                                       close = true;
-                               }
-                       }
-                       if (close) {
-                               try {
-                                       this.transfer_dst.fdatasync();
-                               } catch (x) {}
-                               try {
-                                       this.transfer_dst.close();
-                               } catch (x) {}
-                       }
-               }
-       }
-
-       return close;
-}
-
-/*
- * Updates input timeout expiration time for this FD.
- * To be passed current time in seconds since epoch.
- */
-FD.prototype.updateTimeout = function(time)
-{
-       /* Update input timeout expiration time */
-       this.expires = time + options.io_timeout;
-}
-
-/*
- * Reset FD to a consistent known state, to use after accept(2).
- * To be passed current time in seconds since epoch, and unique id to be used
- * as an index.
- */
-FD.prototype.init = function(time, idx)
-{
-       /* Not a bound socket */
-       this.bound = false;
-       /* Initial state */
-       this.transfer_state = STATE_TRANSFER_READ;
-       this.transfer_src = this.transfer_dst = null;
-       this.transfer_eof = false;
-       this.transfer_data = '';
-       /* Empty request string */
-       this.request_data = '';
-       /* Unique index */
-       this.index = idx;
-       /*
-        * Events interested in.  FD.POLLOUT to be eventually used instead in
-        * transfer state if transfering from server to client.
-        */
-       this.events = FD.POLLIN;
-       /*
-        * Default handler to process this FD, the request state one.
-        * To be changed to the transfer one as needed for transfer state.
-        */
-       this.process = process_query;
-       /* Initial input timeout */
-       this.updateTimeout(time);
-       /* For process_request()/process_post() */
-       this.bread_buffer = this.bwrite_buffer = '';
-       /*
-        * Flag used to speed up request parsing related to old HTTP requests
-        */
-       this.checked_old = false;
-
-       /*
-        * Note that fcntl(2) and setsockopt(2) flags applied to the bound
-        * descriptors are inherited to their children sockets at accept(2).
-        * We therefore can save a few syscalls here.
-        * We are non-blocking already, for instance.
-        */
-}
-
-/*
- * To be called once our client request has been read, to decide what action
- * to perform and modify state accordingly.
- */
-FD.prototype.parseRequest = function(time)
-{
-       var close = valid = false;
-       var evil_browser = evil_os = false;
-       var vhost = '';
-       var lines;
-       var words;
-       var i;
-       var sessid, sess;
-
-       this.http_protocol = '';
-       this.http_method = '';
-       this.http_vhost = undefined;
-       this.http_path = '';
-       this.http_vars_get = {};
-       this.http_vars_post = {};
-       this.http_vars_cookies = {};
-       this.http_agent = '';
-       this.http_content_length = -1;
-       this.http_modified_since = undefined;
-       this.http_sessid = undefined;
-       this.http_vars_session = {};
-       this.http_range = undefined;
-       this.http_old_get = false;
-
-       /* Split request lines */
-       lines = this.request_data.split("\r\n");
-
-       /* Verify if first line has a request which seems valid */
-       if (lines.length > 0) {
-               words = lines[0].split(' ');
-               if (words.length == 2 && words[0] == 'GET') {
-                       this.http_method = words[0];
-                       this.http_path = words[1];
-                       this.http_protocol = 'HTTP/1.1';
-                       this.http_old_get = true;
-                       valid = true;
-               } else if (words.length == 3) {
-                       if ((words[0] == 'GET' || words[0] == 'POST' ||
-                           words[0] == 'PUT') && (words[2] == 'HTTP/1.0' ||
-                           words[2] == 'HTTP/1.1')) {
-                               this.http_method = words[0];
-                               this.http_path = words[1];
-                               this.http_protocol = words[2];
-                               valid = true;
-                       }
-               }
-       }
-
-       /*
-        * Parse header for interesting lines.
-        */
-       if (valid && !this.http_old_get) {
-               for (i in lines) {
-                       words = lines[i].split(' ');
-                       if (words[0] == 'Host:' && words.length == 2) {
-                               var i2;
-
-                               if ((i2 = words[1].indexOf(':')) != -1)
-                                       words[1] = words[1].substr(0, i2);
-                               vhost = words[1];
-                       } else if (words[0] == 'Cookie:') {
-                               words = (lines[i].substr(8)).split('=');
-                               if (words.length == 2)
-                                       property_add(this.http_vars_cookies,
-                                           words[0], words[1]);
-                       } else if (words[0] == 'User-Agent:') {
-                               this.http_agent = lines[i].substr(12);
-                               if (options.ban_msie == true &&
-                                   this.http_agent.indexOf('MSIE') != -1)
-                                       evil_browser = true;
-                               if (options.ban_windows == true &&
-                                   this.http_agent.indexOf('Windows') != -1)
-                                       evil_os = true;
-                       } else if (words[0] == 'Content-Length:' &&
-                                  words.length == 2)
-                               this.http_content_length = words[1].valueOf();
-                       else if (words[0] == 'If-Modified-Since:')
-                               this.http_modified_since = Math.round(
-                                   Date.parse(lines[i].substr(19)) / 1000);
-                       else if (words[0] == 'Range:')
-                               this.http_range = lines[i].substr(7);
-               }
-       }
-
-       /*
-        * If no Host: line set the vhost, set the default one.
-        * If there is a vhost set, but is unknown, also set the default one.
-        * Also set the name of the vhost to the actual vhost name despite
-        * it possibly being resolved through an alias.
-        */
-       if (vhost == '' || vhosts_table[vhost] == undefined)
-               vhost = options.default_vhost;
-       this.http_vhost = vhosts_table[vhost.toLowerCase()];
-
-       if (this.http_old_get && this.http_vhost.scripts) {
-               /*
-                * We only allow old style GET request on static vhosts
-                */
-               this.bwrite('<html><head>' +
-                   '<title>Unsupported Old-Style Request</title></head>' +
-                   '<body><h1>Unsupported Old-Style Request</h1><p>' +
-                   'Your browser sent an old-style HTTP request, which ' +
-                   'this server does not support on dynamic content ' +
-                   'virtual hosts.  Use an HTTP/1.0 or HTTP/1.1 compliant ' +
-                   'client to continue.</p></body></html>' + "\r\n");
-               return true;
-       }
-
-       /*
-        * Filter out definitely invalid requests
-        */
-       if (!valid) {
-               http_error(this, 400, 'Bad Request',
-                   'Your browser sent an invalid HTTP query.');
-               return true;
-       }
-
-       /*
-        * Block out evil Microsoft products.  Start reporting the OS
-        * so that an unwanted windows user doesn't install another
-        * browser to then realize that his OS is banned nevertheless :)
-        */
-       if (evil_os) {
-               http_error(this, 666, 'Evil Operating System Banished!',
-                   'Your Operating System is evil born.<br>At least ' +
-                   '<b>upgrade</b> to a <a href="http://netbsd.org">' +
-                   'decent</a> OS to survive on these grounds.<br>');
-               return true;
-       } else if (evil_browser) {
-               http_error(this, 666, 'Evil Browser Banished!',
-                   'Your browser is evil born.<br>At least ' +
-                   '<b>upgrade</b> to a <a href="http://mozilla.org">' +
-                   'decent</a> browser to survive on these grounds.<br>');
-               return true;
-       }
-
-       /*
-        * Verify if client sent a session cookie, and if it consists of a
-        * valid one, load session data.
-        */
-       if (this.http_vhost.scripts &&
-           (sessid = this.http_vars_cookies['SessionID']) != undefined &&
-           (sess = sessions_table[sessid]) != undefined &&
-           sess.expires > time) {
-               this.http_sessid = sessid;
-               this.http_vars_session = sess.variables;
-       }
-
-       /*
-        * Fill in associative array with any GET-style supplied
-        * variables (as part of the URL).  We want this even for POST method.
-        */
-       if ((i = this.http_path.lastIndexOf('?')) != -1) {
-               var v;
-               var t;
-
-               v = this.http_path.substr(i + 1);
-               /*
-                * Note: substring() and substr() are semantically different
-                */
-               this.http_path = this.http_path.substring(0, i);
-               words = v.split('&');
-               for (i in words) {
-                       t = words[i].split('=');
-                       if (t.length == 2)
-                               property_add(this.http_vars_get, t[0], t[1]);
-               }
-       }
-
-       /*
-        * Switch to POST parsing mode if needed.
-        * This will then call this.parsePost() rather than this function,
-        * which will also invoke this.httpRespond().
-        */
-       if (this.http_method == 'POST' && this.http_content_length != -1) {
-               /*
-                * First obtain buffer stored by process_query() for us,
-                * if any.  If the full post_data was found in it, simply
-                * call the parsing function immediately, which will return
-                * with close status after invking httpRespond().
-                */
-               this.post_data = '';
-               if (this.bread_buffer.length > 0) {
-                       this.post_data += this.bread_buffer;
-                       this.bread_buffer = '';
-               }
-               if (this.post_data.length < this.http_content_length) {
-                       /* Go back to polling, activating process_post */
-                       this.post_data = '';
-                       this.process = process_post;
-                       return false;
-               } else
-                       return this.parsePost(time);
-       }
-
-       if (!close)
-               close = this.httpRespond(time);
-
-       return close;
-}
-
-/*
- * After reading post data, allows to parse it down into variables
- */
-FD.prototype.parsePost = function(time)
-{
-       var words;
-       var i;
-       var t;
-
-       /*
-        * We need to strip "\n", "\r" and "\r\n" which may be sent by broken
-        * clients.
-        */
-       this.post_data = this.post_data.replace(/\n/g, '');
-       this.post_data = this.post_data.replace(/\r/g, '');
-
-       words = this.post_data.split('&');
-       for (i in words) {
-               t = words[i].split('=');
-               if (t.length == 2)
-                       property_add(this.http_vars_post, t[0], t[1]);
-       }
-
-       delete this.post_data;
-
-       return this.httpRespond(time);
-}
-
-/*
- * Finally respond to client request
- */
-FD.prototype.httpRespond = function(time)
-{
-       var path, fd, st, res, ext, mimetype, i, sess, size;
-
-       /*
-        * Verify if requested path is valid
-        */
-       path = this.http_vhost.htdocs_root.valid_virtual(this.http_path);
-       if (!path) {
-               http_error(this, 403, 'Permission Denied',
-                   'You do not have the permission to access this ' +
-                   'resource.');
-               return true;
-       }
-
-       /*
-        * We now want to verify if the client sent a valid session cookie.
-        * If it didn't, we present it with a page with meta-tag reload
-        * instructions to attempt to reload the originally supplied URL,
-        * and with a new session cookie.
-        */
-       if (this.http_vhost.scripts == true && this.http_sessid == undefined) {
-               var doc, sess;
-
-               doc = new HTTPReply(200, 'OK',
-                   'text/html; charset=' + options.default_charset);
-               doc.addNoCacheHeaders();
-
-               sess = new Session(time,
-                   (this.http_vhost.session_exp != undefined ?
-                   this.http_vhost.session_exp :
-                   options.default_session_exp));
-               sess.variables.count = 0;
-               doc.addHeader('Set-Cookie: SessionID=' + sess.sessid +
-                   '; expires=' +
-                   (new Date(sess.expires * 1000)).toGMTString() +
-                   '; path=/');
-               doc.addContent('<html><head><META HTTP-EQUIV="refresh" ' +
-                   'CONTENT="5; URL=' + path.virtual + '"><title>Cookies' +
-                   '</title></head><body><h1>Cookies</h1><p>We are ' +
-                   ' verifying if your browser supports HTTP cookies.  ' +
-                   'These are required to keep persistent session data ' +
-                   'among your connections.  The destination page should ' +
-                   'load automatically in a few seconds.</p>' +
-                   ' <p>If it doesn\'t, please ensure that HTTP cookies ' +
-                   'are enabled on your HTTP client and are accepted ' +
-                   'from this server.</p>' +
-                   '<p>If the page still does not load properly after a ' +
-                   'few seconds, please click on <a href="' + path.virtual +
-                   '">this link</a>.</p><br><sub>' + SERVER_VERSION +
-                   '<br>' + SERVER_CVSID + '</sub>');
-               doc.flush(this, null);
-
-               return true;
-       }
-       if (this.http_sessid != undefined)
-               this.http_vars_session.count++;
-
-
-       /*
-        * Attempt to find requested file.
-        * If it consists of a directory, attempt to first find index.html in
-        * it, then index.jso in it, fail with error 403 if none can be found.
-        * Otherwise, continue forward keeping the descriptor open, and the
-        * stat information already filled in.
-        */
-       fd = new FD();
-
-       try {
-               fd.open(path.real, FD.O_RDONLY);
-               st = fd.fstat();
-       } catch (x) {
-               http_error(this, 404, 'Not Found',
-                   path.virtual + ' could not be found.');
-               return true;
-       }
-
-       if ((st.st_mode & FD.S_IFDIR) != 0) {
-               var error = false;
-
-               fd.close();
-               try {
-                       fd.open(path.real + '/index.html', FD.O_RDONLY);
-                       st = fd.fstat();
-                       path.real += '/index.html';
-                       path.virtual += '/index.html';
-               } catch (x) {
-                       try {
-                               fd.open(path.real + '/index.jso',
-                                   FD.O_RDONLY);
-                               st = fd.fstat();
-                               path.real += '/index.jso';
-                               path.virtual += '/index.jso';
-                       } catch (x) {
-                               error = true;
-                       }
-               }
-               if (error) {
-                       http_error(this, 403, 'Permission Denied',
-                           'You do not have the permission to access the ' +
-                           'resource ' + path.virtual);
-                       return true;
-               }
-       }
-
-       /*
-        * Only continue if file is a regular file
-        */
-       if ((st.st_mode & FD.S_IFREG) == 0) {
-               fd.close();
-               http_error(this, 403, 'Permission Denied',
-                   'You do not have the permission to access the resource ' +
-                   path.virtual);
-               return true;
-       }
-
-       /*
-        * Extract file extension, as well as its mime type.
-        */
-       if ((i = path.virtual.lastIndexOf('.')) != -1) {
-               ext = (path.virtual.substr(i + 1)).toLowerCase();
-               if (ext.lastIndexOf('/') == -1 &&
-                   mimetypes_table[ext] != undefined)
-                       mimetype = mimetypes_table[ext];
-               else
-                       mimetype = options.default_mimetype;
-       }
-       mimetype += '; charset=' + (this.http_vhost.charset == undefined ?
-           options.default_charset : this.http_vhost.charset);
-
-       /*
-        * JavaScript Object (JSO) files are processed especially.
-        * We interpret them, providing them with an environment to
-        * access the needed resources (get/post/cookie/session variables,
-        * as well as the document object they can use).
-        * We flush the document once the script returns, or fire up
-        * an error if something fails.
-        */
-       if (ext == 'jso') {
-
-               /* Create document object */
-               var obj = new HTTPReply(200, 'OK', mimetype);
-               obj.addNoCacheHeaders();
-
-               /* XXX Add other objects to export as necessary */
-               obj.get = this.http_vars_get;
-               obj.post = this.http_vars_post;
-               obj.cookie = this.http_vars_cookies;
-               obj.session = this.http_vars_session;
-               obj.global = this.http_vhost.globals;
-
-               /*
-                * Check if object in our cache already and file not modified
-                * since cached entry.  Reuse function then.  Otherwise,
-                * load in function from file, store a cache entry for it
-                * and launch it.
-                */
-
-               var data, s, o;
-
-               if (((o = jso_cache[path.real]) != undefined) &&
-                   o.time == st.st_mtime) {
-                       obj.script = o.script;
-                       fd.close();
-               } else {
-                       try {
-                               /* file_read() closes fd for us */
-                               data = file_read(fd);
-                               s = 'obj.script = function() {' + data + '}';
-                               eval(s);
-                               o = new JSO(path.real, st.st_mtime,
-                                   obj.script);
-                       } catch (x) {
-                               err.put(x + ' evaluating script ' + path.real
-                                   + "\n");
-                               http_error(this, 500, 'Internal Server Error',
-                                   'Please try again later.');
-                               return true;
-                       }
-               }
-
-               try {
-                       if (obj.script != undefined)
-                               obj.script();
-                       obj.flush(this, null);
-               } catch (x) {
-                       err.put(x + ' executing script ' + path.real + "\n");
-                       http_error(this, 500, 'Internal Server Error',
-                           'Please try again later.');
-               }
-
-               delete obj;
-               return true;
-       }
-
-       /*
-        * If client only wanted the document if it wasn't modified since
-        * a certain time, report that it wasn't if it is the case.
-        */
-       if (this.http_modified_since != undefined &&
-           st.st_mtime <= this.http_modified_since) {
-               fd.close();
-               res = new HTTPReply(304, 'Not Modified', null);
-               res.flush(this, null);
-               return true;
-       }
-
-       /*
-        * If client only requested a range of bytes of the file, verify if
-        * the range is valid, and if so, arrange to only transfer the
-        * requested part of the file.
-        * In any other case, simply transfer the whole file.
-        */
-       if (this.http_range != undefined) {
-               var w;
-
-               if (this.http_range.startsWith('bytes'))
-                       this.http_range = this.http_range.substr(5);
-               if (this.http_range.length > 0 &&
-                   this.http_range.charAt(0) == '=')
-                       this.http_range = this.http_range.substr(1);
-               if ((w = this.http_range.split('-')).length == 2) {
-                       var from, to;
-
-                       if (w[0] == '')
-                               w[0] = 0;
-                       if (w[1] == '')
-                               w[1] = st.st_size - 1;
-                       from = Number(w[0]);
-                       to = Number(w[1]);
-
-                       if (from >= 0 && to < st.st_size && to >= from) {
-                               res = new HTTPReply(206, 'Partial Content',
-                                   mimetype);
-                               res.addHeader('Content-Range: bytes ' +
-                                   from + '-' + to + '/' + st.st_size);
-                               this.transfer_size = Math.abs((to - from) + 1);
-                               if (from > 0) {
-                                       try {
-                                               fd.lseek(from, FD.SEEK_SET);
-                                       } catch(x) {
-                                               err.put(x + " at lseek()\n");
-                                       }
-                               }
-                       }
-               }
-       }
-       if (res == undefined) {
-               res = new HTTPReply(200, 'OK', mimetype);
-               this.transfer_size = Math.abs(st.st_size);
-       }
-
-       /*
-        * Flush HTTP header, sending it
-        */
-       res.flush(this, this.transfer_size);
-
-       /*
-        * Switch to outbound transfer mode.
-        */
-       this.transfer_src = fd;
-       this.transfer_dst = this;
-       this.process = process_transfer;
-       this.events = FD.POLLOUT;
-
-       /*
-        * Return with close=false, to delegate operations to
-        * process_transfer().
-        */
-       return false;
-}
-
-FD.prototype.httpDebug = function()
-{
-       table = new MLTag('table', true);
-       table.addAttr('width', '100%');
-       table.addAttr('border', '1');
-
-       var tr = new MLTag('tr', true);
-       var td = new MLTag('td', true);
-       td.addAttr('width', '10%');
-       td.addAttr('align', 'right');
-       td.addContent('You are:');
-       tr.addContent(td);
-       td = new MLTag('td', true);
-       td.addAttr('width', '90%');
-       td.addContent(this.client_addr + ':' + this.client_port);
-       tr.addContent(td);
-       table.addContent(tr);
-
-       tr = new MLTag('tr', true);
-       td = new MLTag('td', true);
-       td.addAttr('align', 'right');
-       td.addContent('You sent:');
-       tr.addContent(td);
-       td = new MLTag('td', true);
-       var font = new MLTag('font', true);
-       font.addAttr('size', '-3');
-       pre = new MLTag('pre', true);
-       pre.addContent(this.request_data);
-       font.addContent(pre);
-       td.addContent(font);
-       tr.addContent(td);
-       table.addContent(tr);
-
-       tr = new MLTag('tr', true);
-       td = new MLTag('td', true);
-       td.addAttr('align', 'right');
-       td.addContent('GET vars:');
-       tr.addContent(td);
-       td = new MLTag('td', true);
-       var font = new MLTag('font', true);
-       font.addAttr('size', '-3');
-       pre = new MLTag('pre', true);
-       pre.addContent(uneval(this.http_vars_get));
-       font.addContent(pre);
-       td.addContent(font);
-       tr.addContent(td);
-       table.addContent(tr);
-
-       tr = new MLTag('tr', true);
-       td = new MLTag('td', true);
-       td.addAttr('align', 'right');
-       td.addContent('POST vars:');
-       tr.addContent(td);
-       td = new MLTag('td', true);
-       var font = new MLTag('font', true);
-       font.addAttr('size', '-3');
-       pre = new MLTag('pre', true);
-       pre.addContent(uneval(this.http_vars_post));
-       font.addContent(pre);
-       td.addContent(font);
-       tr.addContent(td);
-       table.addContent(tr);
-
-       tr = new MLTag('tr', true);
-       td = new MLTag('td', true);
-       td.addAttr('align', 'right');
-       td.addContent('Cookies:');
-       tr.addContent(td);
-       td = new MLTag('td', true);
-       var font = new MLTag('font', true);
-       font.addAttr('size', '-3');
-       pre = new MLTag('pre', true);
-       pre.addContent(uneval(this.http_vars_cookies));
-       font.addContent(pre);
-       td.addContent(font);
-       tr.addContent(td);
-       table.addContent(tr);
-
-       tr = new MLTag('tr', true);
-       td = new MLTag('td', true);
-       td.addAttr('align', 'right');
-       td.addContent('VHost:');
-       tr.addContent(td);
-       td = new MLTag('td', true);
-       td.addContent(this.http_vhost.name);
-       tr.addContent(td);
-       table.addContent(tr);
-
-       tr = new MLTag('tr', true);
-       td = new MLTag('td', true);
-       td.addAttr('align', 'right');
-       td.addContent('Path:');
-       tr.addContent(td);
-       td = new MLTag('td', true);
-       td.addContent(this.http_path);
-       tr.addContent(td);
-       table.addContent(tr);
-
-       tr = new MLTag('tr', true);
-       td = new MLTag('td', true);
-       td.addAttr('align', 'right');
-       td.addContent('Mod-Since:');
-       tr.addContent(td);
-       td = new MLTag('td', true);
-       td.addContent(this.http_modified_since);
-       tr.addContent(td);
-       table.addContent(tr);
-
-       tr = new MLTag('tr', true);
-       td = new MLTag('td', true);
-       td.addAttr('align', 'right');
-       td.addContent('SessID:');
-       tr.addContent(td);
-       td = new MLTag('td', true);
-       td.addContent(this.http_sessid);
-       tr.addContent(td);
-       table.addContent(tr);
-
-       tr = new MLTag('tr', true);
-       td = new MLTag('td', true);
-       td.addAttr('align', 'right');
-       td.addContent('Sess vars:');
-       tr.addContent(td);
-       td = new MLTag('td', true);
-       var font = new MLTag('font', true);
-       font.addAttr('size', '-3');
-       pre = new MLTag('pre', true);
-       pre.addContent(uneval(this.http_vars_session));
-       font.addContent(pre);
-       td.addContent(font);
-       tr.addContent(td);
-       table.addContent(tr);
-
-       return table.toStr(0);
-}
-
-/*
- * Since we are using nonblocking mode, it is possible for write(2) to return
- * a short count, in which case we must be able to resume writing the
- * remaining buffer after poll(2).  There are currently two write paths,
- * HTTPResponse.flush() and process_transfer().  Both can use this function
- * instead of write(2).  The main poll(2) based loop can then handle buffer
- * flushing.  However, we first attempt to immediately write as much as we can
- * before queuing what needs to be written again.
- * Like write(2), this function can throw an exception on error, including
- * for EAGAIN.
- */
-FD.prototype.bwrite = function(data)
-{
-       var size;
-
-       if ((size = this.write(data)) == data.length)
-               return data.length;
-
-       this.bwrite_buffer += data.substr(size);
-       return size;
-}
-
-/*
- * Called by the main loop to know if there exists queued data, and to write
- * it out if needed.  Returns an object with two properties, done which if
- * true tells the caller that there is no more data to flush, and close
- * which if true means that an error occurred in which case connection should
- * be closed.
- */
-FD.prototype.bwrite_flush = function()
-{
-       var size;
-       var obj = new Object();
-
-       obj.done = obj.close = false;
-
-       if (this.bwrite_buffer.length == 0) {
-               obj.done = true;
-               return obj;
-       }
-
-       b = true;
-       try {
-               size = this.write(this.bwrite_buffer);
-               this.bwrite_buffer = this.bwrite_buffer.substr(size);
-               if (this.bwrite_buffer.length == 0)
-                       obj.done = true;
-       } catch (x) {
-               if (this.errno != Errno.EAGAIN)
-                       obj.close = true;
-       }
-
-       return obj;
-}
-
-/*
- * Verifies if property name ends with [], which considers it as an array of
- * values which are then pushed into that array.
- * Sets the property normally otherwise.
- */
-function property_add(obj, prop, val)
-{
-       prop = unescape(prop.replace(/\+/g, ' '));
-       val = unescape(val.replace(/\+/g, ' '));
-
-       if (prop.endsWith('[]')) {
-               /* Array entry */
-               prop = prop.substring(0, prop.length - 2);
-               if (obj[prop] == undefined)
-                       obj[prop] = [];
-               obj[prop].push(val);
-       } else
-               obj[prop] = val;
-}
-
-
-
-/*
- * To know how many connections we are currently serving and limit them
- */
-var counters_connections = 0;
-var counters_addresses = [];
-
-function counters_inc(fd)
-{
-
-       if (counters_connections >= options.max_connections)
-               return false;
-
-       var addr = fd.client_addr;
-       if ((addrcnt = counters_addresses[addr]) != undefined &&
-           addrcnt >= options.max_connections_addr)
-               return false;
-
-       if (addrcnt == undefined)
-               addrcnt = 1;
-       else
-               addrcnt++;
-       counters_addresses[addr] = addrcnt;
-
-       return true;
-}
-
-function counters_dec(fd)
-{
-       var addr = fd.client_addr;
-       if ((--counters_addresses[addr]) == 0)
-               delete counters_addresses[addr];
-
-       counters_connections--;
-}
-
-
-
-/*
- * Main program
- */
-function main() {
-       var i;
-       var sess_gc_secs = 0;
-
-       /*
-        * Populate vhosts database
-        */
-       for (i in vhosts) {
-               try {
-                       var v = new VHost(vhosts[i]);
-               } catch (x) {
-                       err.put(x + " creating VHost object\n");
-               }
-       }
-       /*
-        * Attempt to link default_vhost to a VHost object
-        */
-       if (options.default_vhost == undefined) {
-               err.put("No default_vhost property in options, exiting\n");
-               exit();
-       }
-       if (vhosts_table[options.default_vhost.toLowerCase()] != undefined)
-               default_vhost =
-                   vhosts_table[options.default_vhost.toLowerCase()];
-       else {
-               err.put('Default vhost ' + options.default_vhost +
-                   " unkonwn, exiting\n");
-               exit();
-       }
-
-       /*
-        * Populate mimetypes database.
-        * XXX If this got very large, because the destination strings
-        * are rather large, it might be good to use indexes or references
-        * to them rather than provide the string for each extension.
-        */
-       for (i in mimetypes) {
-               var i2, ext;
-
-               for (i2 in mimetypes[i]) {
-                       ext = mimetypes[i][i2].toLowerCase();
-                       if (mimetypes_table[ext] != undefined) {
-                               err.put('Conflicting mime type ' +
-                                   ext + ' -> ' + i + "\n");
-                               continue;
-                       }
-                       mimetypes_table[ext] = i;
-               }
-       }
-       if (mimetypes_table['jso'] == undefined)
-               mimetypes_table['jso'] = 'text/html';
-
-       /*
-        * Create polling array set
-        */
-       var set = [];
-
-       /*
-        * Initialize server
-        */
-       for (i in listen) {
-               var fd;
-
-               try {
-                       fd = new FD();
-                       fd.socket(FD.AF_INET, FD.SOCK_STREAM, 0);
-                       fd.bind(listen[i].address, listen[i].port);
-
-                       fd.setsockopt(FD.SO_REUSEADDR, 1);
-                       fd.setsockopt(FD.SO_LINGER, -1);
-                       fd.setsockopt(FD.SO_KEEPALIVE, 1);
-                       fd.setsockopt(FD.TCP_NODELAY, 1);
-
-                       fd.fcntl(FD.F_SETFL, FD.O_NONBLOCK);
-                       fd.listen(options.max_connections);
-                       /*
-                        * Mark socket as bound one and add it to
-                        * polling set
-                        */
-                       fd.events = FD.POLLIN;
-                       fd.bound = true;
-                       set.push(fd);
-               } catch (x) {
-                       err.put(x + " preparing listening socket\n");
-               }
-       }
-       if (set.length == 0)
-               exit();
-
-       /*
-        * Used for unique index associated to each FD for efficient removal
-        * from polling set when closing connection
-        */
-       var count = listen.length + 1;
-
-       /*
-        * Main loop
-        */
-       for (;;) {
-               /*
-                * Determine next to expire FD event, so that we can sleep
-                * as long as possible.  Also get rid of expired requests.
-                */
-               var cur = Date.parse(new Date) / 1000;
-               var exp = cur + 3600;
-               var old;
-               for (i in set) {
-                       var fd;
-
-                       if ((fd = set[i]) == undefined || fd.bound == true)
-                               continue;
-                       if (fd.expires <= cur) {
-                               /*
-                                * Request timeout expired for this
-                                * descriptor, we must close it.
-                                */
-                               fd.close();
-                               counters_dec(fd);
-                               delete set[fd.index];
-                               delete fd;
-                               continue;
-                       }
-                       if (fd.expires < exp)
-                               exp = fd.expires;
-               }
-               exp -= cur;
-
-               /*
-                * Poll our set of descriptors for events
-                */
-               var e;
-               try {
-                       e = FD.poll(set, exp * 1000);
-               } catch (x) {
-                       err.put(x + " for poll(2)\n");
-                       continue;
-               }
-
-               /*
-                * Verify if a timeout occurred.  Because our poll
-                * implementation returns an array, its timeout event can be
-                * checked against by verifying if the set is empty.
-                */
-               if (e.length == 0) {
-                       /* Timeout */
-                       continue;
-               }
-
-               /*
-                * XXX We should perhaps check timeouts after, so that we
-                * only need to query time once per loop?
-                * We could only do this if we knew that all our next
-                * processing is non-blocking, however.  Otherwise we
-                * would loose track of actual time.
-                */
-               old = cur;
-               cur = (Date.parse(new Date) / 1000);
-
-               /*
-                * Verify if we should call the session gc, and if so, do so.
-                */
-               sess_gc_secs += cur - old;
-               if (sess_gc_secs >= options.sess_gc_interval) {
-                       sess_gc_secs = 0;
-                       session_gc(cur);
-               }
-
-               /*
-                * Run through set of descriptors with pending events
-                */
-               for (i in e) {
-                       if (e[i] == undefined)
-                               continue;
-
-                       /*
-                        * If descriptor is a bound one, attempt to accept
-                        * the new client connection
-                        */
-                       if (e[i].bound == true &&
-                           (e[i].revents & FD.POLLIN) != 0) {
-                               var fd;
-
-                               try {
-                                       fd = e[i].accept();
-                                       if (!counters_inc(fd)) {
-                                               http_error(fd, 403.9,
-                                                   'Too Many Connections',
-                                   'Your browser has exceeded its maximum ' +
-                                   'allowed number of concurrent ' +
-                                   'connections.');
-                                               fd.close();
-                                               delete fd;
-                                       } else {
-                                               /*
-                                                * Setup client's initial
-                                                * state and add FD to polling
-                                                * set
-                                                */
-                                               if (++count > 999999)
-                                                       count = listen.length
-                                                          + 1;
-                                               fd.init(cur, count);
-                                               set[count] = fd;
-                                       }
-                               } catch (x) {
-                                       err.put(x + " at accept(2)\n");
-                               }
-                               continue;
-                       }
-
-                       /*
-                        * Not a new connection event
-                        */
-                       var close = false;
-
-                       /*
-                        * Close connection on error conditions,
-                        * Call the FD's process function on interesting
-                        * events, which will tell when we should drop the
-                        * client.
-                        */
-                       if ((e[i].revents & (FD.POLLHUP | FD.POLLERR)) != 0)
-                               close = true;
-                       else if ((e[i].revents & (FD.POLLIN | FD.POLLOUT))
-                           != 0) {
-                               /*
-                                * Flush output queue if any and possible,
-                                * since we're in non-blocking mode writes
-                                * can yield short counts.
-                                */
-                               var o = e[i].bwrite_flush();
-
-                               if (o.close == true)
-                                       close = true;
-                               else if (o.done == true)
-                                       close = e[i].process(cur);
-                       }
-
-                       if (close) {
-                               try {
-                                       e[i].close();
-                               } catch (x) {}
-                               counters_dec(e[i]);
-                               delete set[e[i].index];
-                               delete e[i];
-                       }
-               }
-       }
-
-       /* NOTREACHED */
-       err.close();
-}
-
-main();
-/* NOTREACHED */
-exit(0);
diff --git a/tests/js-test/js/httpd/ml_clean.js b/tests/js-test/js/httpd/ml_clean.js
deleted file mode 100644 (file)
index e0283c6..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/* $Id: ml_clean.js,v 1.4 2005/07/12 13:09:07 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-/*
- * Useful object to use for HTML tags.  <tab> consists of tag name, and
- * <close> of a boolean specifying of the tag requires a corresponding closing
- * tag (i.e. <p>[body]</p>.  Attributes and body elements may be added after
- * creating such an object, and toStr() used to obtain the actual HTML result.
- */
-function MLTag(tag, close)
-{
-       /*
-        * MLTag object properties
-        */
-       this.tag = tag;
-       this.close = close;
-       this.attributes = {};   /* Object with associative attributes */
-       this.contents = [];     /* Array object */
-}
-
-/*
- * Define prototype of the MLTag object.
- */
-MLTag.prototype = {
-       /* A string of spaces to be used for indenting */
-       indent_str: '                                        ' +
-           '                              ',
-
-       /*
-        * Wraps specified string at 70 columns and observing specified
-        * indentation level
-        */
-       wrap: function(str, level)
-       {
-               var len = str.length;
-               var newstr = this.indent_str.substr(0, level);
-               var newlen = level;
-
-               /*
-                * Could find index to space and use substring as necessary
-                * instead of looping through every character.  Of course,
-                * this could also all be implemented using C native code.
-                */
-               for (var i = 0; i < len; i++) {
-                       var c = str.charAt(i);
-
-                       if (c == ' ' && newlen > 70) {
-                               newstr += "\n" + this.indent_str.substr(0,
-                                   level);
-                               newlen = level;
-                               continue;
-                       }
-                       newstr += c;
-                       newlen++;
-               }
-
-               return newstr;
-       },
-
-       /*
-        * Add specified attribute with optional associated value to this tag
-        */
-       addAttr: function(attr, value)
-       {
-
-               this.attributes[attr] = value;
-       },
-
-       /*
-        * Add arbitrary content in sequencial order to this tag's body
-        */
-       addContent: function(item)
-       {
-
-               this.contents.push(item);
-       },
-
-       /*
-        * Returns a string consisting of this tag along with its body and
-        * optional corresponding closing tag
-        */
-       toStr: function(level)
-       {
-               var str = '';
-
-               /* Null tags may exist as containers */
-               if (this.tag != null) {
-
-                       /* Open opening tag */
-                       str += this.indent_str.substr(0, level) + '<' +
-                           this.tag;
-
-                       /*
-                        * Store these immediately for performance since we
-                        * use those values several times later on, also
-                        * saves typing
-                        */
-                       var taglen = this.tag.length;
-                       var len = level + taglen + 1;
-                       var attributes = this.attributes;
-
-                       /*
-                        * Add each of our attributes with their optional
-                        * values
-                        */
-                       for (var attr in attributes) {
-                               var value;
-
-                               if (len > 70) {
-                                       len = level + taglen + 1;
-                                       str += "\n" +
-                                           this.indent_str.substr(0, len);
-                               }
-                               str += ' ' + attr;
-                               len += taglen + 1;
-                               if ((value = attributes[attr]) != null) {
-                                       str += '="' + value + '"';
-                                       len += value.length + 3;
-                               }
-                       }
-
-                       /* Close opening tag */
-                       str += ">\n";
-
-                       /* Increase our indent level for content */
-                       level++;
-
-               }
-
-               /*
-                * Now add all our contents, if any, which may consist of
-                * other MLTag objects or arbitrary String objects.  Use
-                * recursion to process MLTag ones, which may also have their
-                * respective bodies and closing tags.
-                */
-               for (var i in this.contents) {
-                       var a = this.contents[i];
-
-                       if (typeof a == 'object')
-                               str += a.toStr(level);
-                       else
-                               str += this.wrap(a, level) + "\n";
-               }
-
-               /*
-                * If this tag required closing, do so
-                */
-               if (this.tag != null) {
-                       level--;
-                       if (this.close)
-                               str += this.indent_str.substr(0, level) +
-                                   '</' + this.tag + ">\n";
-               }
-
-               return str;
-       }
-}
-
-
-var entitites_table = {
-       '<': '&lt;',
-       '>': '&gt;',
-       '&': '&amp;',
-       '"': '&quot;',
-       "`": '&lsquo;',
-       "'": '&rsquo;'
-};
-
-/*
- * Function to convert a supplied string to use HTML/SGML special entitites.
- * This also allows HTML escaping from user-supplied strings.
- */
-function toHTMLEntities(str)
-{
-       var s = '';
-       var i, t, c, e;
-
-       for (i = 0, t = str.length; i < t; i++) {
-               c = str.charAt(i);
-               if ((e = entitites_table[c]) != undefined)
-                       s += e;
-               else
-                       s += c;
-       }
-
-       return s;
-}
diff --git a/tests/js-test/js/httpd/ml_machine.js b/tests/js-test/js/httpd/ml_machine.js
deleted file mode 100644 (file)
index d9783e9..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/* $Id: ml_machine.js,v 1.4 2005/07/12 13:09:07 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-/*
- * Useful object to use for HTML tags.  <tab> consists of tag name, and
- * <close> of a boolean specifying of the tag requires a corresponding closing
- * tag (i.e. <p>[body]</p>.  Attributes and body elements may be added after
- * creating such an object, and toStr() used to obtain the actual HTML result.
- */
-function MLTag(tag, close)
-{
-       /*
-        * MLTag object properties
-        */
-       this.tag = tag;
-       this.close = close;
-       this.attributes = {};   /* Object with associative attributes */
-       this.contents = [];     /* Array object */
-}
-
-/*
- * Define prototype of the MLTag object.
- */
-MLTag.prototype = {
-
-       /*
-        * Add specified attribute with optional associated value to this tag
-        */
-       addAttr: function(attr, value)
-       {
-
-               this.attributes[attr] = value;
-       },
-
-       /*
-        * Add arbitrary content in sequencial order to this tag's body
-        */
-       addContent: function(item)
-       {
-
-               this.contents.push(item);
-       },
-
-       /*
-        * Returns a string consisting of this tag along with its body and
-        * optional corresponding closing tag
-        */
-       toStr: function(level)
-       {
-               var str = '';
-
-               /* Null tags may exist as containers */
-               if (this.tag != null) {
-
-                       /* Open opening tag */
-                       str += '<' + this.tag;
-
-                       /*
-                        * Store these immediately for performance since we
-                        * use those values several times later on, also
-                        * saves typing
-                        */
-                       var taglen = this.tag.length;
-                       var len = taglen + 1;
-                       var attributes = this.attributes;
-
-                       /*
-                        * Add each of our attributes with their optional
-                        * values
-                        */
-                       for (var attr in attributes) {
-                               var value;
-
-                               str += ' ' + attr;
-                               len += taglen + 1;
-                               if ((value = attributes[attr]) != null) {
-                                       str += '="' + value + '"';
-                                       len += value.length + 3;
-                               }
-                       }
-
-                       /* Close opening tag */
-                       str += ">";
-
-               }
-
-               /*
-                * Now add all our contents, if any, which may consist of
-                * other MLTag objects or arbitrary String objects.  Use
-                * recursion to process MLTag ones, which may also have their
-                * respective bodies and closing tags.
-                */
-               for (var i in this.contents) {
-                       var a = this.contents[i];
-
-                       if (typeof a == 'object')
-                               str += a.toStr(0);
-                       else
-                               str += a;
-               }
-
-               /*
-                * If this tag required closing, do so
-                */
-               if (this.tag != null && this.close)
-                       str += '</' + this.tag + ">";
-
-               return str;
-       }
-
-}
-
-
-var entitites_table = {
-       '<': '&lt;',
-       '>': '&gt;',
-       '&': '&amp;',
-       '"': '&quot;',
-       "`": '&lsquo;',
-       "'": '&rsquo;'
-};
-
-/*
- * Function to convert a supplied string to use HTML/SGML special entitites.
- * This also allows HTML escaping from user-supplied strings.
- */
-function toHTMLEntities(str)
-{
-       var s = '';
-       var i, t, c, e;
-
-       for (i = 0, t = str.length; i < t; i++) {
-               c = str.charAt(i);
-               if ((e = entitites_table[c]) != undefined)
-                       s += e;
-               else
-                       s += c;
-       }
-
-       return s;
-}
diff --git a/tests/js-test/js/httpd/options.js b/tests/js-test/js/httpd/options.js
deleted file mode 100644 (file)
index b0e49c0..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* $Id: options.js,v 1.17 2005/12/12 09:55:45 mmondor Exp $ */
-
-var options = {
-       max_connections:        32,
-       max_connections_addr:   4,
-       io_timeout:             60,
-       readbuf_size:           65536,
-       default_vhost:          "chat.pulsar-zone.net",
-       default_mimetype:       "application/octet-stream",
-       default_charset:        "us-ascii",
-       default_session_exp:    1800,
-       sess_gc_interval:       600,
-       sess_id_size:           64,
-       ban_msie:               false,
-       ban_windows:            false
-};
-
-/* Address:port combinations to listen to */
-var listen = [
-       {
-               address:        "127.0.0.1",
-               port:           8080
-       },
-       {
-               address:        "192.168.1.12",
-               port:           8080
-       }
-];
-
-var vhosts = [
-       /* Default virtual host */
-       {
-               name:           "chat.pulsar-zone.net",
-               root:           "/home/mmondor/jswww/chat",
-               scripts:        true,
-               charset:        'iso-8859-1',
-               session_exp:    14400
-       },
-
-       /* Dynamic application virtual host for ascpi.com */
-       {
-               name:           "ascpi.com",
-               aliases:        [ "www.ascpi.com", "ascpi.hal.xisop",
-                                   "ascpi.hal" ],
-               root:           "/home/mmondor/jswww/ascpi.com"
-       },
-
-       /* Static only test virtual host */
-       {
-               name:           "test.localhost",
-               root:           "/home/mmondor/jswww/welcome"
-       }
-];
-
-var mimetypes  = {
-       'text/html':                            [ "html", "htm", "dhtml",
-                                                   "jso" ],
-       'text/plain':                           [ "txt" ],
-       'text/css':                             [ "css" ],
-       'application/x-xpinstall':              [ "xpi" ],
-       'application/vnd.mozilla.xul+xml':      [ "xul" ],
-       'text/rdf':                             [ "rdf" ],
-       'application/pdf':                      [ "pdf" ],
-       'application/postscript':               [ "ps" ],
-       'application/x-tar':                    [ "tar" ],
-       'application/x-gzip':                   [ "gz" ],
-       'application/x-bzip2':                  [ "bz2" ],
-       'application/zip':                      [ "zip" ],
-       'application/x-javascript':             [ "js" ],
-       'application/x-c':                      [ "c", "h", "cpp", "cc" ],
-       'application/x-sh':                     [ "sh" ],
-       'application/x-shockwave-flash':        [ "swf" ],
-       'application/xml':                      [ "xml" ],
-       'application/xml-dtd':                  [ "dtd" ],
-       'image/jpg':                            [ "jpg", "jpeg" ],
-       'image/png':                            [ "png" ],
-       'image/gif':                            [ "gif" ],
-       'image/x-icon':                         [ "ico" ],
-       'video/mpeg':                           [ "mpeg", "mpg" ],
-       'video/quicktime':                      [ "mov" ],
-       'video/x-msvideo':                      [ "asf", "asx", "wmv", "avi" ]
-};
diff --git a/tests/js-test/js/httpd/root.js b/tests/js-test/js/httpd/root.js
deleted file mode 100644 (file)
index c46fd2b..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/* $Id: root.js,v 1.1 2005/07/07 00:11:43 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Implementation of a virtual chroot(2) system.
- */
-
-
-
-const PATH_MAX = 255;
-
-
-
-function Root(root)
-{
-
-       if (!(this.root = this.valid_path(root)))
-               throw('Invalid root path "' + root + '"!');
-       this.cwd = '/';
-}
-
-Root.prototype = {
-
-       /*
-        * Quick lookup table of valid characters within pathnames.
-        * Currently 'a'-'z', 'A'-'Z', '0'-'9', '.', '/', '-', '_'
-        */
-       valid_char_table: [
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
-               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
-               0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
-               0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-       ],
-
-       /*
-        * Base function to return formatted valid path, or false.
-        * Returned path will always begin with '/' and not have any
-        * trailing '/'.  Multiple '/' are also collapsed into one.
-        */
-       valid_path: function(path)
-       {
-               var i, t, l, p, c, code;
-
-               p = l = '/';
-               for (i = 0, t = path.length; i < t; i++) {
-                       c = path.charAt(i);
-                       if (l == '/') {
-                               /* Collapse multiple '/' */
-                               if (c == '/')
-                                       continue;
-                               /* Prohibit '.' at start of element */
-                               if (c == '.')
-                                       return false;
-                       }
-                       /* Validate chars */
-                       code = c.charCodeAt(0);
-                       if (code != code & 0xff || 
-                           this.valid_char_table[code] == 0)
-                               return false;
-                       p += c;
-                       l = c;
-               }
-               /* Strip last '/' if any, unless only one */
-               if (c == '/' && p.length > 1)
-                       p = p.substr(0, p.length - 1);
-
-               /* If exceeding PATH_MAX, return false */
-               if (p.length > PATH_MAX)
-                       return false;
-
-               return p;
-       },
-
-       /*
-        * Returns version of provided path which points to the parent
-        * directory if possible.  Returns false otherwise.
-        * Should only be used with paths first copied using valid_path().
-        * Can typically be used with the cwd.
-        */
-       parent: function(path)
-       {
-               var i;
-
-               /* First make sure that path starts with '/' */
-               if (path.length < 2 || path.charAt(0) != '/')
-                       return false;
-
-               /* Strip trailing '/' chars */
-               for (i = path.length - 1; i >= 0 && path.charAt(i) == '/';
-                   i--) ;
-               if (i <= path.length)
-                       path = path.substr(0, i + 1);
-
-               /*
-                * Locate previous '/', strip everything after it, including
-                * it, except in the case where it is the only remaining,
-                * where path must remain '/'.
-                */
-               if ((i = path.lastIndexOf('/')) == 0)
-                       i = 1;
-               return path.substring(0, i);
-       },
-
-       /*
-        * This function should always be called when processing user-supplied
-        * paths.  The application should then only trust the object it
-        * returns.  Returns false if the path is invalid.
-        * Otherwise, returns an object, with the following properties:
-        *
-        * <real>       System-wide absolute real fullpath, to be used by the
-        *              application to access the files/directories in
-        *              question.
-        * <virtual>    Virtual root based absolute fullpath, useful to report
-        *              to the user.  Can also be useful to change a Root
-        *              object's cwd to, after verifying that <real> really
-        *              points to an existing directory.
-        */
-       valid_virtual: function(path)
-       {
-               var cwd, c, l, t, o;
-
-               o = {};
-               cwd = this.cwd;
-
-               /*
-                * Look for '~', or '/' in the beginning of the path,
-                * in which case cwd gets cleared to '/'.  Also look for
-                * './' or '.[EOS]', which we simply skip, meaning the
-                * current directory.
-                */
-               if ((l = path.length) > 0) {
-                       c = path.charAt(0);
-                       if (c == '~' || c == '/') {
-                               cwd = '/';
-                               path = path.substr(1);
-                       } else if (c == '.') {
-                               if (l == 1)
-                                       path = '';
-                               else if (l > 1 && path.charAt(1) == '/')
-                                       path = path.substr(2);
-                       }
-               }
-
-               /*
-                * Now process all starting '..' or '../', modifying cwd if
-                * allowed, and stripping them from path.  In case of '../',
-                * also strip any multiple '/'.
-                */
-               for (;;) {
-                       t = false;
-                       l = path.length;
-                       if ((l == 2 && path == '..') ||
-                           (l > 2 && path.substr(0, 2) == '..' &&
-                           (t = (path.charAt(2) == '/')))) {
-                               if (!(cwd = this.parent(cwd)))
-                                       return false;
-                               if (t) {
-                                       for (i = 2; path.charAt(i) == '/';
-                                           i++) ;
-                                       path = path.substr(i);
-                                       continue;
-                               } else {
-                                       path = path.substr(2);
-                                       continue;
-                               }
-                       }
-                       break;
-               }
-
-               /*
-                * Now attempt to fill in our object properties.
-                * this.valid_path() performs necessary sanity checking.
-                */
-               if (!(o.virtual = this.valid_path('/' + cwd + '/' + path)))
-                       return false;
-               o.real = this.root + o.virtual;
-
-               return o;
-       }
-
-};
diff --git a/tests/js-test/js/httpd/string.js b/tests/js-test/js/httpd/string.js
deleted file mode 100644 (file)
index 5ed8080..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/* $Id: string.js,v 1.1 2005/07/11 01:50:56 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Extension to the standard String object to support startsWith() and
- * endsWith() very useful methods.
- */
-
-
-
-String.prototype.startsWith = function(str)
-{
-       var t = str.length;
-
-       if (this.length >= t && this.substr(0, t) == str)
-               return true;
-
-       return false;
-}
-
-String.prototype.endsWith = function(str)
-{
-       var t1 = str.length;
-       var t2 = this.length;
-
-       if (t2 >= t1 && this.substr(t2 - t1, t1) == str)
-               return true;
-
-       return false;
-}
diff --git a/tests/js-test/js/ml.js b/tests/js-test/js/ml.js
deleted file mode 100644 (file)
index dd09de6..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/* $Id: ml.js,v 1.4 2005/06/27 18:21:21 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-const ident_str = '                                                  ' +
-    '                    ';
-
-function indent(level)
-{
-       if (level == null)
-               return false;
-
-       return ident_str.substr(0, level);
-}
-
-function wrap(str, level)
-{
-       if (str == null || level == null)
-               return false;
-
-       var len = str.length;
-       var newstr = indent(level);
-       var newlen = level;
-       var i;
-
-       /*
-        * Could find index to space and use substring as necessary instead of
-        * looping through every character.  Of course, this could also all be
-        * implemented using C native code.
-        */
-       for (i = 0; i < len; i++) {
-               if (str.charAt(i) == ' ' && newlen > 70) {
-                       newstr += "\n" + indent(level);
-                       newlen = level;
-                       continue;
-               }
-               newstr += str.charAt(i);
-               newlen++;
-       }
-
-       return newstr;
-}
-
-
-
-function MLAttr(attr, value)
-{
-       /* We allow null value */
-       if (attr == null)
-               return false;
-
-       this.attr = attr;
-       this.value = value;
-}
-
-
-
-/*
- * XXX Using prototypes to inherit functions would be ideal for speed,
- * probably, to avoid having to redeclare the functions in the constructor for
- * every new object instance.  However, I seemed to have problems when using
- * that method, mostly related to the constructor of the object no longer
- * being tracable.
- */
-
-function MLTag(attr, close)
-{
-       if (attr == null || close == null)
-               return false;
-
-       this.attr = attr;
-       this.close = close;
-       this.attributes = new Array();
-       this.attributes_count = 0;
-       this.contents = new Array();
-       this.contents_count = 0;
-
-       this.addAttr = function(attr, value)
-       {
-               if (attr == null)
-                       return false;
-
-               this.attributes[this.attributes_count++] =
-                   new MLAttr(attr, value);
-       }
-
-       this.addContent = function(item)
-       {
-               if (item == null)
-                       return false;
-
-               this.contents[this.contents_count++] = item;
-       }
-
-       this.toStr = function(level)
-       {
-               if (level == null)
-                       return false;
-
-               var str = '';
-               var i, attrlen, len, a;
-
-               str += indent(level) + '<' + this.attr;
-               attrlen = this.attr.length;
-               len = level + attrlen + 1;
-               for (i = 0; i < this.attributes_count; i++) {
-                       a = this.attributes[i];
-
-                       if (len > 70) {
-                               len = level + attrlen + 1;
-                               str += "\n" + indent(len);
-                       }
-                       str += ' ' + a.attr;
-                       len += attrlen + 1;
-                       if (a.value != null) {
-                               var value = a.value;
-                               str += '="' + value + '"';
-                               len += value.length + 3;
-                       }
-               }
-               str += ">\n";
-
-               if (this.close)
-                       level++;
-
-               for (i = 0; i < this.contents_count; i++) {
-                       a = this.contents[i];
-
-                       if (typeof a == 'object')
-                               str += a.toStr(level);
-                       else
-                               str += wrap(a, level) + "\n";
-               }
-
-               if (this.close)
-                       str += indent(--level) + '</' + this.attr + ">\n";
-
-               return str;
-       }
-}
-
-
-
-/*
- * Now test our functionality
- */
-
-out = new FD();
-out.set(FD.STDOUT_FILENO);
-
-for (i = 0; i < 1000; i++) {
-
-var table = new MLTag('table', true);
-table.addAttr('border', 0);
-table.addAttr('width', '100%');
-
-var tr = new MLTag('tr', true);
-
-var td = new MLTag('td', true);
-td.addAttr('bgcolor', '#000000');
-
-var p = new MLTag('p', true);
-p.addContent('Hello');
-
-td.addContent(p);
-tr.addContent(td);
-table.addContent(tr);
-
-out.put(table.toStr(8));
-
-//out.put(uneval(table));
-
-}
diff --git a/tests/js-test/js/ml2.js b/tests/js-test/js/ml2.js
deleted file mode 100644 (file)
index 6a1eab6..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/* $Id: ml2.js,v 1.3 2005/06/27 19:45:22 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * XXX Using prototypes to inherit functions would be ideal for speed,
- * probably, to avoid having to redeclare the functions in the constructor for
- * every new object instance.  However, I seemed to have problems when using
- * that method, mostly related to the constructor of the object no longer
- * being tracable.  At worse, we could define our methods as MLTag_foo() and
- * in the constructor function just assign them to the proper properties...
- * The currently used method at least has advantage of being cleaner to read.
- */
-
-/*
- * Useful object to use for HTML tags.  <tab> consists of tag name, and
- * <close> of a boolean specifying of the tag requires a corresponding closing
- * tag (i.e. <p>[body]</p>.  Attributes and body elements may be added after
- * creating such an object, and toStr() used to obtain the actual HTML result.
- */
-function MLTag(tag, close)
-{
-       if (tag == null || close == null)
-               return false;
-
-       /*
-        * A few utility functions used by our methods later on.
-        * Adding these here prevents namespace pollution.
-        */
-
-       /* Returns a string with requested number of spaces */
-       const indent_str = '                                        ' +
-           '                              ';
-       this.indent = function(level)
-       {
-               if (level == null)
-                       return false;
-
-               return indent_str.substr(0, level);
-       }
-
-       /*
-        * Wraps specified string at 70 columns and observing specified
-        * indentation level
-        */
-       this.wrap = function(str, level)
-       {
-               if (str == null || level == null)
-                       return false;
-
-               var len = str.length;
-               var newstr = this.indent(level);
-               var newlen = level;
-
-               /*
-                * Could find index to space and use substring as necessary
-                * instead of looping through every character.  Of course,
-                * this could also all be implemented using C native code.
-                */
-               for (var i = 0; i < len; i++) {
-                       var c = str.charAt(i);
-
-                       if (c == ' ' && newlen > 70) {
-                               newstr += "\n" + this.indent(level);
-                               newlen = level;
-                               continue;
-                       }
-                       newstr += c;
-                       newlen++;
-               }
-
-               return newstr;
-       }
-
-
-       /*
-        * MLTag object properties
-        */
-       this.tag = tag;
-       this.close = close;
-       this.attributes = new Object();
-       this.contents = new Array();
-       this.contents_count = 0;
-
-       /*
-        * Add specified attribute with optional associated value to this tag
-        */
-       this.addAttr = function(attr, value)
-       {
-               if (attr == null)
-                       return false;
-
-               eval('this.attributes.' + attr + ' = \'' + value + '\'');
-       }
-
-       /*
-        * Add arbitrary content in sequencial order to this tag's body
-        */
-       this.addContent = function(item)
-       {
-               if (item == null)
-                       return false;
-
-               this.contents[this.contents_count++] = item;
-       }
-
-       /*
-        * Returns a string consisting of this tag along with its body and
-        * optional corresponding closing tag
-        */
-       this.toStr = function(level)
-       {
-               if (level == null)
-                       return false;
-
-               /* Open opening tag */
-               var str = this.indent(level) + '<' + this.tag;
-
-               /*
-                * Store these immediately for performance since we use those
-                * values several times later on, also saves typing
-                */
-               var taglen = this.tag.length;
-               var len = level + taglen + 1;
-               var attributes = this.attributes;
-
-               /* Add each of our attributes with their optional values */
-               for (var attr in attributes) {
-                       var value;
-
-                       if (len > 70) {
-                               len = level + taglen + 1;
-                               str += "\n" + this.indent(len);
-                       }
-                       str += ' ' + attr;
-                       len += taglen + 1;
-                       if ((value = attributes[attr]) != null) {
-                               str += '="' + value + '"';
-                               len += value.length + 3;
-                       }
-               }
-               /* Close opening tag */
-               str += ">\n";
-
-               /* Increase our indent level for content */
-               level++;
-
-               /*
-                * Now add all our contents, if any, which may consist of
-                * other MLTag objects or arbitrary String objects.  Use
-                * recursion to process MLTag ones, which may also have their
-                * respective bodies and closing tags.
-                */
-               for (var i = 0; i < this.contents_count; i++) {
-                       var a = this.contents[i];
-
-                       if (typeof a == 'object')
-                               str += a.toStr(level);
-                       else
-                               str += this.wrap(a, level) + "\n";
-               }
-
-               /*
-                * This tag required closing, so add corresponding closing tag
-                * and decrease indent level.
-                */
-               level--;
-               if (this.close)
-                       str += this.indent(level) + '</' + this.tag + ">\n";
-
-               return str;
-       }
-}
-
-
-
-/*
- * Now test our functionality
- */
-
-out = new FD();
-out.set(FD.STDOUT_FILENO);
-
-for (i = 0; i < 1000; i++) {
-
-var table = new MLTag('table', true);
-table.addAttr('border', 0);
-table.addAttr('width', '100%');
-
-var tr = new MLTag('tr', true);
-
-var td = new MLTag('td', true);
-td.addAttr('bgcolor', '#000000');
-
-var p = new MLTag('p', true);
-p.addContent('Hello');
-
-td.addContent(p);
-tr.addContent(td);
-table.addContent(tr);
-
-out.put(table.toStr(8));
-
-//out.put(uneval(table));
-
-}
diff --git a/tests/js-test/js/ml3.js b/tests/js-test/js/ml3.js
deleted file mode 100644 (file)
index 3b8cb3b..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/* $Id: ml3.js,v 1.3 2005/06/27 19:45:22 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * XXX Using prototypes to inherit functions would be ideal for speed,
- * probably, to avoid having to redeclare the functions in the constructor for
- * every new object instance.  However, I seemed to have problems when using
- * that method, mostly related to the constructor of the object no longer
- * being tracable.  At worse, we could define our methods as MLTag_foo() and
- * in the constructor function just assign them to the proper properties...
- * The currently used method at least has advantage of being cleaner to read.
- */
-
-/*
- * Useful object to use for HTML tags.  <tab> consists of tag name, and
- * <close> of a boolean specifying of the tag requires a corresponding closing
- * tag (i.e. <p>[body]</p>.  Attributes and body elements may be added after
- * creating such an object, and toStr() used to obtain the actual HTML result.
- */
-function MLTag(tag, close)
-{
-       if (tag == null || close == null)
-               return false;
-
-       /*
-        * A few utility functions used by our methods later on.
-        * Adding these here prevents namespace pollution.
-        */
-
-       /* Returns a string with requested number of spaces */
-       const indent_str = '                                        ' +
-           '                              ';
-       this.indent = function(level)
-       {
-               if (level == null)
-                       return false;
-
-               return indent_str.substr(0, level);
-       }
-
-       /*
-        * Wraps specified string at 70 columns and observing specified
-        * indentation level
-        */
-       this.wrap = function(str, level)
-       {
-               if (str == null || level == null)
-                       return false;
-
-               var len = str.length;
-               var newstr = this.indent(level);
-               var newlen = level;
-
-               /*
-                * Could find index to space and use substring as necessary
-                * instead of looping through every character.  Of course,
-                * this could also all be implemented using C native code.
-                */
-               for (var i = 0; i < len; i++) {
-                       var c = str.charAt(i);
-
-                       if (c == ' ' && newlen > 70) {
-                               newstr += "\n" + this.indent(level);
-                               newlen = level;
-                               continue;
-                       }
-                       newstr += c;
-                       newlen++;
-               }
-
-               return newstr;
-       }
-
-
-       /*
-        * MLTag object properties
-        */
-       this.tag = tag;
-       this.close = close;
-       this.attributes = new Array();  /* Associative */
-       this.contents = new Array();
-       this.contents_count = 0;
-
-       /*
-        * Add specified attribute with optional associated value to this tag
-        */
-       this.addAttr = function(attr, value)
-       {
-               if (attr == null)
-                       return false;
-
-               this.attributes[attr] = value;
-       }
-
-       /*
-        * Add arbitrary content in sequencial order to this tag's body
-        */
-       this.addContent = function(item)
-       {
-               if (item == null)
-                       return false;
-
-               this.contents[this.contents_count++] = item;
-       }
-
-       /*
-        * Returns a string consisting of this tag along with its body and
-        * optional corresponding closing tag
-        */
-       this.toStr = function(level)
-       {
-               if (level == null)
-                       return false;
-
-               /* Open opening tag */
-               var str = this.indent(level) + '<' + this.tag;
-
-               /*
-                * Store these immediately for performance since we use those
-                * values several times later on, also saves typing
-                */
-               var taglen = this.tag.length;
-               var len = level + taglen + 1;
-               var attributes = this.attributes;
-
-               /* Add each of our attributes with their optional values */
-               for (var attr in attributes) {
-                       var value;
-
-                       if (len > 70) {
-                               len = level + taglen + 1;
-                               str += "\n" + this.indent(len);
-                       }
-                       str += ' ' + attr;
-                       len += taglen + 1;
-                       if ((value = attributes[attr]) != null) {
-                               str += '="' + value + '"';
-                               len += value.length + 3;
-                       }
-               }
-               /* Close opening tag */
-               str += ">\n";
-
-               /* Increase our indent level for content */
-               level++;
-
-               /*
-                * Now add all our contents, if any, which may consist of
-                * other MLTag objects or arbitrary String objects.  Use
-                * recursion to process MLTag ones, which may also have their
-                * respective bodies and closing tags.
-                */
-               for (var i = 0; i < this.contents_count; i++) {
-                       var a = this.contents[i];
-
-                       if (typeof a == 'object')
-                               str += a.toStr(level);
-                       else
-                               str += this.wrap(a, level) + "\n";
-               }
-
-               /*
-                * This tag required closing, so add corresponding closing tag
-                * and decrease indent level.
-                */
-               level--;
-               if (this.close)
-                       str += this.indent(level) + '</' + this.tag + ">\n";
-
-               return str;
-       }
-}
-
-
-
-/*
- * Now test our functionality
- */
-
-out = new FD();
-out.set(FD.STDOUT_FILENO);
-
-for (i = 0; i < 1000; i++) {
-
-var table = new MLTag('table', true);
-table.addAttr('border', 0);
-table.addAttr('width', '100%');
-
-var tr = new MLTag('tr', true);
-
-var td = new MLTag('td', true);
-td.addAttr('bgcolor', '#000000');
-
-var p = new MLTag('p', true);
-p.addContent('Hello');
-
-td.addContent(p);
-tr.addContent(td);
-table.addContent(tr);
-
-out.put(table.toStr(8));
-
-//out.put(uneval(table));
-
-}
diff --git a/tests/js-test/js/ml4.js b/tests/js-test/js/ml4.js
deleted file mode 100644 (file)
index e2d3383..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/* $Id: ml4.js,v 1.5 2005/06/27 19:45:22 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-/*
- * Useful object to use for HTML tags.  <tab> consists of tag name, and
- * <close> of a boolean specifying of the tag requires a corresponding closing
- * tag (i.e. <p>[body]</p>.  Attributes and body elements may be added after
- * creating such an object, and toStr() used to obtain the actual HTML result.
- */
-function MLTag(tag, close)
-{
-       if (tag == null || close == null)
-               return false;
-
-       /*
-        * MLTag object properties
-        */
-       this.tag = tag;
-       this.close = close;
-       this.attributes = {};   /* Object with associative attributes */
-       this.contents = [];     /* Array object */
-}
-
-/*
- * Force creation of prototype object
- */
-MLTag('prototype', false);
-
-/*
- * A few utility functions used by our methods later on.
- * Adding these here prevents namespace pollution.
- */
-
-MLTag.prototype.indent_str = '                                        ' +
-    '                              ';
-/* Returns a string with requested number of spaces */
-MLTag.prototype.indent = function(level)
-{
-       if (level == null)
-               return false;
-
-       return this.indent_str.substr(0, level);
-}
-
-/*
- * Wraps specified string at 70 columns and observing specified
- * indentation level
- */
-MLTag.prototype.wrap = function(str, level)
-{
-       if (str == null || level == null)
-               return false;
-
-       var len = str.length;
-       var newstr = this.indent(level);
-       var newlen = level;
-
-       /*
-        * Could find index to space and use substring as necessary
-        * instead of looping through every character.  Of course,
-        * this could also all be implemented using C native code.
-        */
-       for (var i = 0; i < len; i++) {
-               var c = str.charAt(i);
-
-               if (c == ' ' && newlen > 70) {
-                       newstr += "\n" + this.indent(level);
-                       newlen = level;
-                       continue;
-               }
-               newstr += c;
-               newlen++;
-       }
-
-       return newstr;
-}
-
-/*
- * Add specified attribute with optional associated value to this tag
- */
-MLTag.prototype.addAttr = function(attr, value)
-{
-       if (attr == null)
-               return false;
-
-       this.attributes[attr] = value;
-}
-
-/*
- * Add arbitrary content in sequencial order to this tag's body
- */
-MLTag.prototype.addContent = function(item)
-{
-       if (item == null)
-               return false;
-
-       this.contents.push(item);
-}
-
-/*
- * Returns a string consisting of this tag along with its body and
- * optional corresponding closing tag
- */
-MLTag.prototype.toStr = function(level)
-{
-       if (level == null)
-               return false;
-
-       /* Open opening tag */
-       var str = this.indent(level) + '<' + this.tag;
-
-       /*
-        * Store these immediately for performance since we use those
-        * values several times later on, also saves typing
-        */
-       var taglen = this.tag.length;
-       var len = level + taglen + 1;
-       var attributes = this.attributes;
-
-       /* Add each of our attributes with their optional values */
-       for (var attr in attributes) {
-               var value;
-
-               if (len > 70) {
-                       len = level + taglen + 1;
-                       str += "\n" + this.indent(len);
-               }
-               str += ' ' + attr;
-               len += taglen + 1;
-               if ((value = attributes[attr]) != null) {
-                       str += '="' + value + '"';
-                       len += value.length + 3;
-               }
-       }
-       /* Close opening tag */
-       str += ">\n";
-
-       /* Increase our indent level for content */
-       level++;
-
-       /*
-        * Now add all our contents, if any, which may consist of
-        * other MLTag objects or arbitrary String objects.  Use
-        * recursion to process MLTag ones, which may also have their
-        * respective bodies and closing tags.
-        */
-       for (var i = 0; i < this.contents.length; i++) {
-               var a = this.contents[i];
-
-               if (typeof a == 'object')
-                       str += a.toStr(level);
-               else
-                       str += this.wrap(a, level) + "\n";
-       }
-
-       /*
-        * This tag required closing, so add corresponding closing tag
-        * and decrease indent level.
-        */
-       level--;
-       if (this.close)
-               str += this.indent(level) + '</' + this.tag + ">\n";
-
-       return str;
-}
-
-
-
-/*
- * Now test our functionality
- */
-
-out = new FD();
-out.set(FD.STDOUT_FILENO);
-
-for (i = 0; i < 1000; i++) {
-
-var table = new MLTag('table', true);
-table.addAttr('border', 0);
-table.addAttr('width', '100%');
-
-var tr = new MLTag('tr', true);
-
-var td = new MLTag('td', true);
-td.addAttr('bgcolor', '#000000');
-
-var p = new MLTag('p', true);
-p.addContent('Hello');
-
-td.addContent(p);
-tr.addContent(td);
-table.addContent(tr);
-
-out.put(table.toStr(8));
-
-//out.put(uneval(table));
-
-}
diff --git a/tests/js-test/js/ml5.js b/tests/js-test/js/ml5.js
deleted file mode 100644 (file)
index 9c7b772..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/* $Id: ml5.js,v 1.3 2005/06/27 19:45:22 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-/*
- * Useful object to use for HTML tags.  <tab> consists of tag name, and
- * <close> of a boolean specifying of the tag requires a corresponding closing
- * tag (i.e. <p>[body]</p>.  Attributes and body elements may be added after
- * creating such an object, and toStr() used to obtain the actual HTML result.
- */
-function MLTag(tag, close)
-{
-       /*
-       if (tag == null || close == null)
-               return false;
-        */
-
-       /*
-        * MLTag object properties
-        */
-       this.tag = tag;
-       this.close = close;
-       this.attributes = {};   /* Object with associative attributes */
-       this.contents = [];     /* Array object */
-}
-
-/*
- * Define prototype of the MLTag object.
- */
-MLTag.prototype = {
-       /* A string of spaces to be used by indent() */
-       indent_str: '                                        ' +
-           '                              ',
-
-       /* Returns a string with requested number of spaces */
-       indent: function(level)
-       {
-               /*
-               if (level == null)
-                       return false;
-                */
-
-               return this.indent_str.substr(0, level);
-       },
-
-       /*
-        * Wraps specified string at 70 columns and observing specified
-        * indentation level
-        */
-       wrap: function(str, level)
-       {
-               /*
-               if (str == null || level == null)
-                       return false;
-                */
-
-               var len = str.length;
-               var newstr = this.indent(level);
-               var newlen = level;
-
-               /*
-                * Could find index to space and use substring as necessary
-                * instead of looping through every character.  Of course,
-                * this could also all be implemented using C native code.
-                */
-               for (var i = 0; i < len; i++) {
-                       var c = str.charAt(i);
-
-                       if (c == ' ' && newlen > 70) {
-                               newstr += "\n" + this.indent(level);
-                               newlen = level;
-                               continue;
-                       }
-                       newstr += c;
-                       newlen++;
-               }
-
-               return newstr;
-       },
-
-       /*
-        * Add specified attribute with optional associated value to this tag
-        */
-       addAttr: function(attr, value)
-       {
-               /*
-               if (attr == null)
-                       return false;
-                */
-
-               this.attributes[attr] = value;
-       },
-
-       /*
-        * Add arbitrary content in sequencial order to this tag's body
-        */
-       addContent: function(item)
-       {
-               /*
-               if (item == null)
-                       return false;
-                */
-
-               this.contents.push(item);
-       },
-
-       /*
-        * Returns a string consisting of this tag along with its body and
-        * optional corresponding closing tag
-        */
-       toStr: function(level)
-       {
-               /*
-               if (level == null)
-                       return false;
-                */
-
-               /* Open opening tag */
-               var str = this.indent(level) + '<' + this.tag;
-
-               /*
-                * Store these immediately for performance since we use those
-                * values several times later on, also saves typing
-                */
-               var taglen = this.tag.length;
-               var len = level + taglen + 1;
-               var attributes = this.attributes;
-
-               /* Add each of our attributes with their optional values */
-               for (var attr in attributes) {
-                       var value;
-
-                       if (len > 70) {
-                               len = level + taglen + 1;
-                               str += "\n" + this.indent(len);
-                       }
-                       str += ' ' + attr;
-                       len += taglen + 1;
-                       if ((value = attributes[attr]) != null) {
-                               str += '="' + value + '"';
-                               len += value.length + 3;
-                       }
-               }
-               /* Close opening tag */
-               str += ">\n";
-
-               /* Increase our indent level for content */
-               level++;
-
-               /*
-                * Now add all our contents, if any, which may consist of
-                * other MLTag objects or arbitrary String objects.  Use
-                * recursion to process MLTag ones, which may also have their
-                * respective bodies and closing tags.
-                */
-               for (var i = 0; i < this.contents.length; i++) {
-                       var a = this.contents[i];
-
-                       if (typeof a == 'object')
-                               str += a.toStr(level);
-                       else
-                               str += this.wrap(a, level) + "\n";
-               }
-
-               /*
-                * This tag required closing, so add corresponding closing tag
-                * and decrease indent level.
-                */
-               level--;
-               if (this.close)
-                       str += this.indent(level) + '</' + this.tag + ">\n";
-
-               return str;
-       }
-}
-
-
-
-
-/*
- * Now test our functionality
- */
-
-out = new FD();
-out.set(FD.STDOUT_FILENO);
-
-for (i = 0; i < 1000; i++) {
-
-var table = new MLTag('table', true);
-table.addAttr('border', 0);
-table.addAttr('width', '100%');
-
-var tr = new MLTag('tr', true);
-
-var td = new MLTag('td', true);
-td.addAttr('bgcolor', '#000000');
-
-var p = new MLTag('p', true);
-p.addContent('Hello');
-
-td.addContent(p);
-tr.addContent(td);
-table.addContent(tr);
-
-out.put(table.toStr(8));
-
-//out.put(uneval(table));
-
-}
diff --git a/tests/js-test/js/ml6.js b/tests/js-test/js/ml6.js
deleted file mode 100644 (file)
index 15c3b8c..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/* $Id: ml6.js,v 1.1 2005/11/16 00:35:01 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-/*
- * Useful object to use for HTML tags.  <tab> consists of tag name, and
- * <close> of a boolean specifying of the tag requires a corresponding closing
- * tag (i.e. <p>[body]</p>.  Attributes and body elements may be added after
- * creating such an object, and toStr() used to obtain the actual HTML result.
- */
-function MLTag(tag, close)
-{
-       /*
-        * MLTag object properties
-        */
-       this.tag = tag;
-       this.close = close;
-       this.attributes = {};   /* Object with associative attributes */
-       this.contents = [];     /* Array object */
-}
-
-/*
- * Define prototype of the MLTag object.
- */
-MLTag.prototype = {
-       /* A string of spaces to be used for indenting */
-       indent_str: '                                        ' +
-           '                              ',
-
-       /*
-        * Wraps specified string at 70 columns and observing specified
-        * indentation level
-        */
-       wrap: function(str, level)
-       {
-               var len = str.length;
-               var newstr = this.indent_str.substr(0, level);
-               var newlen = level;
-
-               /*
-                * Could find index to space and use substring as necessary
-                * instead of looping through every character.  Of course,
-                * this could also all be implemented using C native code.
-                */
-               for (var i = 0; i < len; i++) {
-                       var c = str.charAt(i);
-
-                       if (c == ' ' && newlen > 70) {
-                               newstr += "\n" + this.indent_str.substr(0,
-                                   level);
-                               newlen = level;
-                               continue;
-                       }
-                       newstr += c;
-                       newlen++;
-               }
-
-               return newstr;
-       },
-
-       /*
-        * Add specified attribute with optional associated value to this tag
-        */
-       addAttr: function(attr, value)
-       {
-
-               this.attributes[attr] = value;
-       },
-
-       /*
-        * Add arbitrary content in sequencial order to this tag's body
-        */
-       addContent: function(item)
-       {
-
-               this.contents.push(item);
-       },
-
-       /*
-        * Returns a string consisting of this tag along with its body and
-        * optional corresponding closing tag
-        */
-       toStr: function(level)
-       {
-
-               /* Open opening tag */
-               var str = this.indent_str.substr(0, level) + '<' + this.tag;
-
-               /*
-                * Store these immediately for performance since we use those
-                * values several times later on, also saves typing
-                */
-               var taglen = this.tag.length;
-               var len = level + taglen + 1;
-               var attributes = this.attributes;
-
-               /* Add each of our attributes with their optional values */
-               for (var attr in attributes) {
-                       var value;
-
-                       if (len > 70) {
-                               len = level + taglen + 1;
-                               str += "\n" + this.indent_str.substr(0, len);
-                       }
-                       str += ' ' + attr;
-                       len += taglen + 1;
-                       if ((value = attributes[attr]) != null) {
-                               str += '="' + value + '"';
-                               len += value.length + 3;
-                       }
-               }
-               /* Close opening tag */
-               str += ">\n";
-
-               /* Increase our indent level for content */
-               level++;
-
-               /*
-                * Now add all our contents, if any, which may consist of
-                * other MLTag objects or arbitrary String objects.  Use
-                * recursion to process MLTag ones, which may also have their
-                * respective bodies and closing tags.
-                */
-               for (var i = 0; i < this.contents.length; i++) {
-                       var a = this.contents[i];
-
-                       if (typeof a == 'object')
-                               str += a.toStr(level);
-                       else
-                               str += this.wrap(a, level) + "\n";
-               }
-
-               /*
-                * This tag required closing, so add corresponding closing tag
-                * and decrease indent level.
-                */
-               level--;
-               if (this.close)
-                       str += this.indent_str.substr(0, level) + '</' +
-                           this.tag + ">\n";
-
-               return str;
-       }
-}
-
-
-
-
-/*
- * Now test our functionality
- */
-
-out = new FD();
-out.set(FD.STDOUT_FILENO);
-
-for (i = 0; i < 1000; i++) {
-
-var table = new MLTag('table', true);
-table.addAttr('border', 0);
-table.addAttr('width', '100%');
-
-var tr = new MLTag('tr', true);
-
-var td = new MLTag('td', true);
-td.addAttr('bgcolor', '#000000');
-
-var p = new MLTag('p', true);
-p.addContent('Hello');
-
-td.addContent(p);
-tr.addContent(td);
-table.addContent(tr);
-
-out.put(table.toStr(8));
-
-//out.put(uneval(table));
-
-}
diff --git a/tests/js-test/js/parse.js b/tests/js-test/js/parse.js
deleted file mode 100644 (file)
index 672b115..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-/* $Id: parse.js,v 1.1 2005/11/16 00:36:58 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-/*
- * Useful object to use for HTML tags.  <tab> consists of tag name, and
- * <close> of a boolean specifying of the tag requires a corresponding closing
- * tag (i.e. <p>[body]</p>.  Attributes and body elements may be added after
- * creating such an object, and toStr() used to obtain the actual HTML result.
- */
-function MLTag(tag, close)
-{
-       /*
-        * MLTag object properties
-        */
-       this.tag = tag;
-       this.close = close;
-       this.attributes = {};   /* Object with associative attributes */
-       this.contents = [];     /* Array object */
-}
-
-/*
- * Define prototype of the MLTag object.
- */
-MLTag.prototype = {
-
-       /*
-        * Add specified attribute with optional associated value to this tag
-        */
-       addAttr: function(attr, value)
-       {
-
-               this.attributes[attr] = value;
-       },
-
-       /*
-        * Add arbitrary content in sequencial order to this tag's body
-        */
-       addContent: function(item)
-       {
-
-               this.contents.push(item);
-       },
-
-       /*
-        * Returns a string consisting of this tag along with its body and
-        * optional corresponding closing tag
-        */
-       toStr: function(level)
-       {
-               var str = '';
-
-               /* Null tags may exist as containers */
-               if (this.tag != null) {
-
-                       /* Open opening tag */
-                       str += '<' + this.tag;
-
-                       /*
-                        * Store these immediately for performance since we
-                        * use those values several times later on, also
-                        * saves typing
-                        */
-                       var taglen = this.tag.length;
-                       var len = taglen + 1;
-                       var attributes = this.attributes;
-
-                       /*
-                        * Add each of our attributes with their optional
-                        * values
-                        */
-                       for (var attr in attributes) {
-                               var value;
-
-                               str += ' ' + attr;
-                               len += taglen + 1;
-                               if ((value = attributes[attr]) != null) {
-                                       str += '="' + value + '"';
-                                       len += value.length + 3;
-                               }
-                       }
-
-                       /* Close opening tag */
-                       str += ">";
-
-               }
-
-               /*
-                * Now add all our contents, if any, which may consist of
-                * other MLTag objects or arbitrary String objects.  Use
-                * recursion to process MLTag ones, which may also have their
-                * respective bodies and closing tags.
-                */
-               for (var i = 0; i < this.contents.length; i++) {
-                       var a = this.contents[i];
-
-                       if (typeof a == 'object')
-                               str += a.toStr(0);
-                       else
-                               str += a;
-               }
-
-               /*
-                * If this tag required closing, do so
-                */
-               if (this.tag != null && this.close)
-                       str += '</' + this.tag + ">";
-
-               return str;
-       }
-
-}
-
-
-var entitites_table = {
-       '<': '&lt;',
-       '>': '&gt;',
-       '&': '&amp;',
-       '"': '&quot;',
-       "`": '&lsquo;',
-       "'": '&rsquo;'
-};
-
-/*
- * Function to convert a supplied string to use HTML/SGML special entitites.
- * This also allows HTML escaping from user-supplied strings.
- */
-function toHTMLEntities(str)
-{
-       var s = '';
-       var i, t, c, e;
-
-       for (i = 0, t = str.length; i < t; i++) {
-               c = str.charAt(i);
-               if ((e = entitites_table[c]) != undefined)
-                       s += e;
-               else
-                       s += c;
-       }
-
-       return s;
-}
-
-
-
-/*
- * This is a parsing test.
- *
- * For now, we want to simply accept patterns in the form %x{...}, where
- * there may be arbitrary data within the { }, and function %x must be
- * performed on it.  For instance, %b{some text} would denote this text
- * as bold.  However, we should also allow %b{some text %i{more text}} and
- * such.  Because %, { and } characters are special, we should support
- * escaping with \.  Because \ is special for escaping, we should support
- * \\ meaning a single \.  Unclosed } should either generate an error,
- * or we might want to automatically consider them all closed at the end
- * of the user provided string.
- *
- * XXX One level currently seems to work, but there are recursive problems!
- * Also, we are loosing a space.
- */
-
-function tokenize(str, ctag, i)
-{
-       var t, c;
-       var escaped = false;
-       var tags = new MLTag(null, false);
-       var ss = '';
-
-       if (ctag != undefined) {
-               if (str.length < i || str.charAt(i) != '{')
-                       return tags;
-               i++;
-       } else
-               i = 0;
-
-       for (t = str.length; i < t; i++) {
-               c = str.charAt(i);
-
-               /* Handle '\' escaping, valid for the whole string */
-               if (escaped &&
-                   (c == '\\' || c == '%' || c == '{' || c == '}')) {
-                       ss += c;
-                       escaped = false;
-                       continue;
-               }
-               if (c == '\\') {
-                       escaped = true;
-                       continue;
-               }
-
-               /*
-                * Special character which delimits commands strings. Since
-                * we are recursively called we must detect this condition and
-                * exit just like for the end of string.
-                */
-               if (c == '{' || c == '}' && ctag == undefined) {
-                       ss += c;
-                       continue;
-               }
-               if (c == '}') {
-//                     i++;    /* XXX */
-                       break;
-               }
-
-               /*
-                * Command mode.  Make sure that we do have a command name,
-                * followed with required '{'.  If an invalid command, simply
-                * allow enclosed string to be litteral.  For valid commands,
-                * create the required tag and recurse into ourselves on the
-                * enclosed string in '{' and '}'.
-                */
-               /* Command mode */
-               if (c == '%') {
-                       var ntag, o;
-
-                       if (/*ctag != undefined ||*/ i > t - 1 ||
-                           str.charAt(i + 2) != '{') {
-                               ss += c;
-                               continue;
-                       }
-
-                       /* Flush current string if any */
-                       if (ss.length > 0) {
-                               tags.addContent(ss);
-                               ss = '';
-                       }
-
-                       switch (str.charAt(i + 1)) {
-                       case 'b':
-                               ntag = new MLTag('b', true);
-                               break;
-                       case 'i':
-                               ntag = new MLTag('i', true);
-                               break;
-                       case 'e':
-                               ntag = new MLTag('em', true);
-                               break;
-                       case 'S':
-                               ntag = new MLTag('sup', true);
-                               break;
-                       case 's':
-                               ntag = new MLTag('sub', true);
-                               break;
-                       case 't':
-                               ntag = new MLTag('tt', true);
-                               break;
-                       case 'h':
-                               ntag = new MLTag('h', true);
-                               break;
-                       case 'p':
-                               ntag = new MLTag('p', true);
-                               break;
-                       case 'n':
-                               ntag = new MLTag('br', false);
-                               break;
-                       case 'A':
-                               ntag = new MLTag('a', true);
-                               break;
-                       case 'I':
-                               ntag = new MLTag('img', true);
-                               break;
-                       default:
-                               ntag = new MLTag(null, false);
-                       }
-
-                       o = tokenize(str, ntag, i + 2);
-                       i = o.i;
-                       /* XXX */
-                       ntag.addContent(o.tags.toStr(0));
-                       tags.addContent(ntag);
-                       continue;
-               }
-
-               ss += c;
-       }
-
-       /*
-        * Now that we gathered command-enclosed string, take care of special
-        * cases for <a> and <img>, and add resulting content.
-        */
-       if (ctag != undefined) {
-               switch (ctag.tag) {
-               case 'a':
-                       ctag.addAttr('href', ss);
-                       break;
-               case 'img':
-                       ctag.addAttr('src', ss);
-                       break;
-               }
-               if (ss.length > 0) {
-                       ctag.addContent(ss);
-                       ss = '';
-               }
-               tags.addContent(ctag);
-       }
-       if (ss.length > 0)
-               tags.addContent(ss);
-
-       /*
-        * Return object with current index in string, as well as new tag
-        * container
-        */
-       var obj = {};
-       obj.i = i;
-       obj.tags = tags;
-
-       return obj;
-}
-
-
-//print((tokenize('Some %b{enclosed} string', undefined, 0)).tags.toStr(0));
-print((tokenize('Some %b{enclo%i{s}ed} string', undefined, 0)).tags.toStr(0));
-//print(uneval((tokenize('Some %b{enclo%i{s}ed} string', undefined, 0)).tags));
diff --git a/tests/js-test/js/poll_test.js b/tests/js-test/js/poll_test.js
deleted file mode 100644 (file)
index ba04111..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/* $Id: poll_test.js,v 1.3 2005/02/13 09:02:06 mmondor Exp $ */
-
-function events(e)
-{
-       s = new String();
-
-       if (e & FD.POLLIN)
-               s += 'POLLIN ';
-       if (e & FD.POLLOUT)
-               s += 'POLLOUT ';
-       if (e & FD.POLLERR)
-               s += 'POLLERR ';
-       if (e & FD.POLLHUP)
-               s += 'POLLHUP ';
-       if (e & FD.POLLNVAL)
-               s += 'POLLNVAL ';
-
-       return s;
-}
-
-output = new FD();
-output.set(FD.STDOUT_FILENO);
-
-try {
-
-       input = new FD();
-       input.set(FD.STDIN_FILENO);
-
-       set = new Array();
-
-       /*
-        * This is interesting, because we allow normal arrays, either dense
-        * using set.push(), or sparse using set[n] = fd, but we also allow
-        * associative array elements such as set['string'] = fd.  The
-        * returned set only holds FD objects for which events occurred.  One
-        * can run through that resulting set using for (v in a) ... format,
-        * but it is also possible to verify the associative string name to
-        * see if it is in the set.  As usual with poll(2), POLLHUP, POLLERR
-        * and POLLNVAL are always possible even for descriptor objects with
-        * their events property set to 0.  The default events property for
-        * an FD object is also 0.  The user can then verify the revents
-        * property of each FD object in the result set, and take appropriate
-        * I/O action or processing.
-        *
-        * Moreover, JavaScript being a very dynamic language, one can add
-        * properties or methods to individual FD objects as wanted, and of
-        * course can use those to say, process events of the descriptors
-        * returned in the set with pending events.  This means that a common
-        * method name with different functionality added to each FD object
-        * permits a main events loop to transparently execute the wanted code
-        * using, for instance, fd.process().  In a case where two types of
-        * common events, input and output need to be processed differently
-        * with such a method, one can even define new methods as a prototype
-        * for base custom FD objects, which can be automatically inherited
-        * in shared mode by all children objects derived from the prototype
-        * object.
-        */
-
-       /*
-        * Set interesting events mask for our FD objects to monitor
-        */
-       input.events = FD.POLLIN;
-       output.events = 0;
-
-       /*
-        * Add our FD objects to an array
-        */
-       set.push(input);
-       set.push(output);
-
-       /*
-        * Invoke poll(2) on descriptors in our FD objects array, sleep for a
-        * maximum of 5000 milliseconds (5 seconds).  Retreive result set of
-        * FD objects with pending events into rset.
-        */
-       rset = FD.poll(set, 5000);
-
-       /*
-        * Display rset contents
-        */
-       output.put('Set size: ' + rset.length + "\n");
-       for (var i in rset) {
-               output.put(i + ': type=' + rset[i].constructor.name + ' fd=' +
-                   rset[i].fd + ' revents=' + events(rset[i].revents) + "\n");
-       }
-
-       input.close();
-
-} catch (x) {
-       output.put(x + "\n");
-}
-
-output.close();
diff --git a/tests/js-test/js/sock_httpd.js b/tests/js-test/js/sock_httpd.js
deleted file mode 100644 (file)
index d12533b..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-/* $Id: sock_httpd.js,v 1.8 2005/06/28 00:19:03 mmondor Exp $ */
-
-/*
- * Little example showing the versatility of ECMAScript, provided with a
- * custom library for BSD socket support, using SpiderMonkey.
- * This tiny HTTPd allows simultaneous concurrent client connections without
- * using multiple threads or processes.  Must be ran through ../src/test,
- * compiled with ../src/classes/js_fd.[ch] support.
- *
- * We support a maximum of 4 concurrent connections per IP address, as well
- * as a total maximum of 32 concurrent connections by default.
- * Change MAX_CONNECTIONS and MAX_CONNECTIONS_ADDR as needed.
- *
- * We also support per-connection request timeouts, defaulting to 60 seconds.
- * Change REQUEST_TIMEOUT as wanted.
- * Note that this timeout consists of a total timeout for the connection,
- * rather than an actual input timeout (which would require to reset the
- * expiration time everytime user input occurs).  Using the current timeout
- * method suits most embedded applications, but would not be adequate to
- * support large file transfers or the like (connection would timeout
- * during a long transfer).  However, if we supported this kind of long
- * file transfers, because we are single-threaded, we would need two states
- * in our machine, one where small requests take place, and another
- * specialized for ongoing file transfers.  Although this could be
- * implemented, it was not a required functionality for this demonstration.
- */
-
-
-
-/*
- * Configuration
- */
-const MAX_CONNECTIONS          = 32;
-const MAX_CONNECTIONS_ADDR     = 4;
-const REQUEST_TIMEOUT          = 60;
-
-
-
-/*
- * Open standard error FD for diagnostics output
- */
-err = new FD();
-err.set(FD.STDERR_FILENO);
-
-
-/*
- * Initialize server
- */
-try {
-       sock = new FD();
-       sock.socket(FD.AF_INET, FD.SOCK_STREAM, 0);
-       sock.bind('127.0.0.1', 1337);
-       sock.listen(MAX_CONNECTIONS);
-} catch (x) {
-       err.put(x + "\n");
-       exit();
-}
-
-
-/*
- * Create polling array set and insert bound socket in it
- */
-var set = [];
-sock.events = FD.POLLIN;
-set['bind'] = sock;
-
-
-
-/*
- * Used for unique index associated to each FD for efficient removal from
- * polling set when closing connection
- */
-var count = 0;
-
-
-/*
- * To know how many connections we are currently serving and limit them
- */
-var connections = 0;
-var addresses = [];
-
-function counters_inc(fd)
-{
-       if (connections >= MAX_CONNECTIONS)
-               return false;
-
-       var addr = fd.client_addr;
-       if ((addrcnt = addresses[addr]) != undefined &&
-           addrcnt >= MAX_CONNECTIONS_ADDR)
-               return false;
-
-       if (addrcnt == undefined)
-               addrcnt = 1;
-       else
-               addrcnt++;
-       addresses[addr] = addrcnt;
-
-       return true;
-}
-
-function counters_dec(fd)
-{
-       var addr = fd.client_addr;
-       if ((--addresses[addr]) == 0)
-               delete addresses[addr];
-
-       connections--;
-}
-
-
-/*
- * Handles client request and replies back
- */
-function handle_request(fd)
-{
-       try {
-               fd.put(
-                   "HTTP/1.1 200\r\n" +
-                   "Content-type: text/html\r\n" +
-                   "Server: js/1\r\n" +
-                   "Connection: close\r\n" +
-                   "\r\n" +
-                   "<HTML><HEAD><TITLE>Detected!</TITLE></HEAD>\n" +
-                   "<BODY><PRE>\n" +
-                   "You are: " + fd.client_addr + ":" + fd.client_port +
-                   "\n" + "ID: " + fd.index + "\n\n" +
-                   "You sent:\n" + fd.request + "\n" +
-                   "</PRE>\n" + "<P>Tracing in progress...</P>\n" +
-                   "</BODY></HTML>\r\n");
-       } catch (x) {}
-}
-
-
-/*
- * Main server loop
- */
-for (;;) {
-       try {
-
-               /*
-                * Determine next to expire FD event, so that we can sleep
-                * as long as possible.  Also get rid of expired requests.
-                */
-               var cur = Date.parse(new Date) / 1000;
-               var exp = cur + 3600;
-               for (i in set) {
-                       var fd;
-
-                       if ((fd = set[i]) == undefined || i == 'bind')
-                               continue;
-                       if (fd.expires <= cur) {
-                               /*
-                                * Request timeout expired for this
-                                * descriptor, we must close it.
-                                */
-                               fd.close();
-                               counters_dec(fd);
-                               delete set[fd.index];
-                               delete fd;
-                               continue;
-                       }
-                       if (fd.expires < exp)
-                               exp = fd.expires;
-               }
-               exp -= cur;
-
-               /*
-                * Poll our set of descriptors for events
-                */
-               var e = FD.poll(set, exp * 1000);
-               /*
-                * Verify if a timeout occurred.  Because our poll
-                * implementation returns an array, its timeout event can be
-                * checked against by verifying if the set is empty.  However,
-                * associative-array/object-attributes are not accounted
-                * properly with 'length' in JS, so also test fo the case of
-                * the 'bind' entry.
-                */
-               if (e.length == 0 && e['bind'] == undefined) {
-                       /* Timeout */
-                       continue;
-               }
-
-               /*
-                * Process occurred events.  First handle new connections,
-                * if any.
-                */
-               if (e['bind'] != undefined) {
-                       /*
-                        * New connection, accept it
-                        */
-                       var fd = sock.accept();
-
-                       if (!counters_inc(fd)) {
-                               fd.put("HTTP/1.1 403.9\r\n" + 
-                                   "Connection: close\r\n\r\n");
-                               fd.close();
-                               delete fd;
-                       } else {
-                               /*
-                                * Associate a new string with FD object
-                                * which will serve to hold the client request
-                                */
-                               fd.request = '';
-                               /*
-                                * We add this custom property to efficiently
-                                * be able to remove FD from polling set later
-                                * on
-                                */
-                               count++;
-                               fd.index = count;
-                               /*
-                                * Set its interesting polling event to
-                                * POLLIN
-                                */
-                               fd.events = FD.POLLIN;
-                               /*
-                                * Also set request expiration time
-                                */
-                               fd.expires = (Date.parse(new Date) / 1000) +
-                                   REQUEST_TIMEOUT;
-                               /*
-                                * Add descriptor to polling set
-                                */
-                               set[count] = fd;
-                       }
-               }
-
-               /*
-                * Run through set of descriptors with pending events
-                */
-               for (i in e) {
-                       if (e[i] == undefined || i == 'bind')
-                               continue;
-                       if ((e[i].revents & (FD.POLLHUP | FD.POLLERR)) != 0) {
-                               /*
-                                * Unexpected connection loss, close and
-                                * remove from polling set.
-                                */
-                               e[i].close();
-                               counters_dec(e[i]);
-                               delete set[e[i].index];
-                               delete e[i];
-                       } else if ((e[i].revents & FD.POLLIN) != 0) {
-                               var l, close = false;
-
-                               /*
-                                * New data to read from this FD, add to
-                                * request string, verify if we should answer
-                                * and close connection.
-                                * We also limit the maximum request length.
-                                */
-                               if ((l = e[i].get()) != null) {
-                                       if (e[i].length > 32768)
-                                               close = true;
-                                       else
-                                               e[i].request += l;
-                                       if (e[i].request.search("\r\n\r\n")
-                                           != -1)
-                                               close = true;
-                               } else
-                                       close = true;
-
-                               if (close) {
-                                       /*
-                                        * Answer and close connection
-                                        */
-                                       handle_request(e[i]);
-                                       e[i].close();
-                                       counters_dec(e[i]);
-                                       /*
-                                        * Nice feature, we can hint the
-                                        * GC about the fact that we no
-                                        * longer refer to, or want these,
-                                        * which saves RAM since it avoids
-                                        * caching many old useless objects.
-                                        */
-                                       delete set[e[i].index];
-                                       delete e[i];
-                               }
-                       }
-               }
-       } catch (x) {
-               err.put(x + "\n");
-       }
-}
-
-
-/* NOTREACHED */
-
-sock.close();
-err.close();
diff --git a/tests/js-test/js/sock_listen.js b/tests/js-test/js/sock_listen.js
deleted file mode 100644 (file)
index 55f19e1..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* $Id: sock_listen.js,v 1.4 2005/04/20 08:50:06 mmondor Exp $ */
-
-err = new FD();
-err.set(FD.STDERR_FILENO);
-
-try {
-       sock = new FD();
-       sock.socket(FD.AF_INET, FD.SOCK_STREAM, 0);
-       sock.bind('127.0.0.1', 1337);
-       sock.listen(10);
-} catch (x) {
-       err.put(x + "\n");
-}
-
-var req = '';
-for (;;) {
-       try {
-               fd = sock.accept();
-               try {
-                       req = '';
-                       while (req.length < 32768) {
-                               if ((l = fd.get()) == null)
-                                       break;
-                               req += l;
-                               if (l.search("\r\n\r\n"))
-                                       break;
-                       }
-                       /*
-                        * Note: because I was asked a few times about this,
-                        * the following is a joke :) we actually don't care
-                        * about the client and won't traceroute, we only
-                        * want client connections to test the program.
-                        */
-                       fd.put("HTTP/1.1 200\r\nServer: js/1\r\n" +
-                           "Connection: close\r\n" + "\r\n");
-                       fd.put("<HTML><HEAD><TITLE>Detected!</TITLE></HEAD>" +
-                           "<BODY><PRE>\n");
-                       fd.put("You are: " + fd.client_addr + ":" +
-                           fd.client_port + "\n\nYou sent:\n" + req + "\n");
-                       fd.put("</PRE>\n" + "<P>Tracing in progress...</P>\n" +
-                           "</BODY></HTML>\r\n");
-               } catch (y) {
-                       err.put(y + "\n");
-               }
-               fd.close();
-       } catch (x) {
-               err.put(x + "\n");
-       }
-}
-
-sock.close();
-err.close();
diff --git a/tests/js-test/js/test.js b/tests/js-test/js/test.js
deleted file mode 100644 (file)
index b27fc71..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* $Id: test.js,v 1.1 2004/12/27 11:16:15 mmondor Exp $ */
-
-
-/*
- * The following test should not succeed on API class
- */
-
-/* {{ */
-
-/*
-function test(s)
-{
-       API.print(s);
-}
-
-API.test = test;
-API.test("Successfully added method to API class!\n");
-API.test2 = "Successfully added property to API class!\n";
-API.test(API.test2 + "\n");
-*/
-
-/* }} */
-
-
-
-/*
- * These tests should succeed, however.
- */
-
-API.print("API.property1 = " + API.property1 + "\n");
-API.print("API.property2 = " + API.property2 + "\n");
-API.print("API.property3 = " + API.property3 + "\n\n");
-
-/*
- * XXX
- * These fail, even though these are permanent and read/write properties.
- * JS_SealObject() seems to be converting all read/write properties to
- * report an error if setProperty() method is called. However, interestingly
- * enough, read/only properties report no error. However, they obviously
- * are not modified despite attempts to assign them new values.
- */
-API.property1 = 'Hello';
-API.property2 = 911;
-
-/*
- * Following statement should fail, but is simply internally ignored at least
- * (the setProperty() method is not called).
- */
-API.property3 = 'READONLY!';
-
-API.print("API.property1 = " + API.property1 + "\n");
-API.print("API.property2 = " + API.property2 + "\n");
-API.print("API.property3 = " + API.property3 + "\n\n");
-
-
-
-/*
- * Perform a test loop, during which callMe() should be called by the
- * application code, via the break callback handler function.
- */
-for (i = 0; i < 3; i++) {
-       API.print("We are the: " + Date() + "\n");
-       API.print("NetBSD Kernel size is " +
-           (API.fileSize("/netbsd") / 1024 / 1024) + "MB\n");
-       API.print("END\n");
-}
-API.print("\n");
-
-
-
-/*
- * Will be called by our application if we create it
- */
-function callMe(n)
-{
-       API.print("CallMe(" + n + ")!\n");
-}
-
-
-
-/*
- * Interesting feature where we can return a value explicitely, optionally
- */
-10
diff --git a/tests/js-test/js/test2.js b/tests/js-test/js/test2.js
deleted file mode 100644 (file)
index 5cb105e..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id: test2.js,v 1.4 2005/02/05 08:07:35 mmondor Exp $ */
-
-var file;
-
-try {
-       file = new API.File("/etc/hosts");
-       API.print("File '" + file.path + "' is loaded (" + file.size +
-           ") bytes.\n");
-       file.release();
-} catch (x) {
-       API.print("Exception: " + x + "\n");
-       exit();
-}
-
-API.print("Finishing...\n");
diff --git a/tests/js-test/js/test3.js b/tests/js-test/js/test3.js
deleted file mode 100644 (file)
index c683324..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-function Employee() {
-       this.name = "";
-       this.dept = "general";
-}
-
-function Manager() {
-       this.reports = [];
-}
-Manager.prototype = new Employee;
-
-function WorkerBee() {
-       this.projects = [];
-}
-WorkerBee.prototype = new Employee;
-
-function SalesPerson() {
-       this.dept = "sales";
-       this.quota = 100;
-}
-SalesPerson.prototype = new WorkerBee;
-
-function Engineer() {
-       this.dept = "engineering";
-       this.machine = "";
-}
-Engineer.prototype = new WorkerBee;
-
-t = Engineer;
-var eng
-eng = new t();
-API.print(typeof eng + ', ' + eng.constructor.name);
-API.print("\n");
-
-/* Interesting test. Dynamically create properties i0 - i9 */
-list = new Object;
-for (i = 0; i < 10; i++) {
-       c = 'list.i' + i + ' = ' + i * i;
-       eval(c);
-}
-/* And print the values of our i0 - i9 previously created properties. */
-for (i = 0; i < 10; i++) {
-       c = 'API.print(\'' + 'list.i' + i + ' = \' + list.i' + i + ' + "\\n")';
-       eval(c);  
-}
-
-API.print("\nEND\n");
diff --git a/tests/js-test/src/GNUmakefile b/tests/js-test/src/GNUmakefile
deleted file mode 100644 (file)
index 828cfae..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-# $Id: GNUmakefile,v 1.9 2006/07/17 08:55:18 mmondor Exp $
-
-#CFLAGS += -g
-CFLAGS += -Wall
-
-JS_CFLAGS := $(shell spidermonkey-config -dc)
-JS_LDFLAGS := $(shell spidermonkey-config -dl)
-
-PG_CFLAGS := $(shell pg_config --cppflags)
-PG_LDFLAGS := $(shell pg_config --ldflags)
-PG_LDFLAGS += -lpq
-
-OBJS := $(addprefix classes/,js_fd.o js_errno.o js_signal.o js_pgsql.o)
-OBJS += js-server.o
-
-CFLAGS += $(JS_CFLAGS) $(PG_CFLAGS) -Iclasses -Wall
-LDFLAGS += $(JS_LDFLAGS) $(PG_LDFLAGS)
-
-
-all: js-server
-
-%.o: %.c
-       cc -c ${CFLAGS} -o $@ $<
-
-js-server: $(OBJS)
-       cc -o $@ -lc ${LDFLAGS} $(OBJS)
-
-clean:
-       rm -f js-server $(OBJS)
diff --git a/tests/js-test/src/classes/js_errno.c b/tests/js-test/src/classes/js_errno.c
deleted file mode 100644 (file)
index af58462..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/* $Id: js_errno.c,v 1.3 2005/12/12 09:55:15 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Basic UNIX errno services for ECMAScript
- */
-
-
-
-#include <sys/types.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-
-
-/* Utility macros */
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-
-/* Prototypes */
-static JSBool  errno_sm_strerror(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-
-
-/* Actual class parameters */
-static JSClass errno_class = {
-       "Errno", 0, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
-};
-
-/* Provided static methods */
-static JSFunctionSpec errno_smethods[] = {
-       { "strerror", errno_sm_strerror, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/*
- * Provided static properties.
- * We use these to provide ECMAScript with the ability to use system-specific
- * standard C constant macros without us having to tidiously map them
- * individually, or to require other scripts to be used as headers to define
- * them.  Another possibility would have been to supply these parameters as
- * string, but this would have required even slower remapping because of the
- * parsing and string comparisions.
- * We only include those which we consider necessary for now, others may be
- * added easily as needed, provided that they are added in all three maps.
- * I might perhaps develop macros and/or functions to map all these easily
- * from a single map.
- */
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-#define SP(n) \
-    { #n, n }
-
-static struct property_spec    errno_sprops[] = {
-       SP(EPERM),
-       SP(ENOENT),
-       SP(EINTR),
-       SP(EIO),
-       SP(ENXIO),
-       SP(EBADF),
-       SP(EACCES),
-       SP(ENOTBLK),
-       SP(EBUSY),
-       SP(EEXIST),
-       SP(EXDEV),
-       SP(ENODEV),
-       SP(ENOTDIR),
-       SP(EISDIR),
-       SP(EINVAL),
-       SP(ENFILE),
-       SP(EMFILE),
-       SP(ENOTTY),
-       SP(ETXTBSY),
-       SP(EFBIG),
-       SP(ENOSPC),
-       SP(ESPIPE),
-       SP(EROFS),
-       SP(EMLINK),
-       SP(EPIPE),
-       SP(EAGAIN),
-       SP(EINPROGRESS),
-       SP(EALREADY),
-       SP(ENOTSOCK),
-       SP(EDESTADDRREQ),
-       SP(EMSGSIZE),
-       SP(EPROTOTYPE),
-       SP(EPROTONOSUPPORT),
-       SP(EOPNOTSUPP),
-       SP(EPFNOSUPPORT),
-       SP(EAFNOSUPPORT),
-       SP(EADDRINUSE),
-       SP(EADDRNOTAVAIL),
-       SP(ENETDOWN),
-       SP(ENETUNREACH),
-       SP(ENETRESET),
-       SP(ECONNABORTED),
-       SP(ECONNRESET),
-       SP(ENOBUFS),
-       SP(EISCONN),
-       SP(ENOTCONN),
-       SP(ESHUTDOWN),
-       SP(ETIMEDOUT),
-       SP(ECONNREFUSED),
-       SP(ELOOP),
-       SP(ENAMETOOLONG),
-       SP(EHOSTDOWN),
-       SP(EHOSTUNREACH),
-       SP(ENOTEMPTY),
-       SP(EDQUOT),
-       SP(ESTALE),
-       SP(ENOLCK),
-       SP(ENOSYS),
-       SP(EFTYPE),
-       SP(ENOMSG),
-       SP(ENOTSUP),
-       SP(ECANCELED),
-       SP(EBADMSG),
-       SP(ENODATA),
-       SP(ETIME),
-
-       { NULL, 0 }
-};
-
-#undef SP
-
-
-
-/*
- * Class control functions
- */
-
-JSObject *
-js_InitErrnoClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &errno_class, NULL,
-           0, NULL, NULL, NULL, errno_smethods)) == NULL) {
-               (void) fprintf(stderr, "Error initializing Errno class\n");
-               return NULL;
-       }
-
-       /* Create static properties */
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "Errno: JS_GetConstructor == NULL\n");
-               return NULL;
-       }
-       for (sp = errno_sprops; sp->name != NULL; sp++) {
-               if (JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT) == JS_FALSE) {
-                       (void) fprintf(stderr,
-                           "Errno: Error defining property %s\n", sp->name);
-                       return NULL;
-               }
-       }
-
-       return proto;
-}
-
-
-
-/*
- * Static properties functions
- */
-
-
-
-/*
- * Static methods
- */
-
-static JSBool
-errno_sm_strerror(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       int             error;
-       JSString        *string;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(*argv)) {
-               QUEUE_EXCEPTION("Argument not an integer");
-               return JS_FALSE;
-       }
-       error = (int)JSVAL_TO_INT(*argv);
-
-       if ((string = JS_NewStringCopyZ(cx, strerror(error))) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               return JS_FALSE;
-       }
-
-       *rval = STRING_TO_JSVAL(string);
-
-       return JS_TRUE;
-}
diff --git a/tests/js-test/src/classes/js_errno.h b/tests/js-test/src/classes/js_errno.h
deleted file mode 100644 (file)
index 22b69bb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: js_errno.h,v 1.2 2005/07/19 19:25:44 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSERRNO_H
-#define JSERRNO_H
-
-extern JSObject        *js_InitErrnoClass(JSContext *, JSObject *);
-
-#endif
diff --git a/tests/js-test/src/classes/js_fd.c b/tests/js-test/src/classes/js_fd.c
deleted file mode 100644 (file)
index e0f8a1a..0000000
+++ /dev/null
@@ -1,1971 +0,0 @@
-/* $Id: js_fd.c,v 1.42 2006/07/11 10:25:51 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Basic UNIX filedescriptor and BSD sockets services for ECMAScript
- */
-
-/*
- * XXX TODO XXX
- * - Possibly create a byte buffer type
- * - Add path based restrictions to open()
- * - (maybe) add restrictions to bind()
- * - Either add stat() or provide equivalent properties
- * - Enhance exception reports.  Function name should be provided, and
- *   errno should be displayed when wanted. Perhaps that jsfd->error could
- *   also be set automatically when an exception is generated which involves
- *   errno.
- *   - Check JS_ReportError().
- * - Moving finalizer freeing and close() freeing code to a common function
- *   might be a good idea.
- * - Add getnameinfo()/getaddrinfo() ? Or should we transparently allow this
- *   through properties?
- * - Add send()/sendto()/sendmsg(), recv()/recvfrom()/recvmsg() ...
- * - It is possible that we need to verify that obj is instance of FD in all
- *   methods, perhaps.  I.E. consider an FD method assigned on another object.
- * - Add hostname to address and address to hostname resolution facilities
- * - Maybe also add properties for local end address/port of socket
- * - Would be nice to experiment with a fork(2) heh.  If so, if we allow
- *   fcntl(2) close-on-exec flag, we should make sure to mark FD objects as
- *   closed too for an execve(2) wrapper.
- * - popen(2), would probably need to use custom execve(2) wrapper above...
- * - Add support to easily restrict an application's right to functions.
- *   Path and mode sanity checking functions should also be written and their
- *   parameters set on a per-application basis.
- * - Maybe virtual chdir(2)
- * - A stdio FILE extension object might be nice, with stuff like fdopen() to
- *   create one...  This would be most useful for buffered lined based input
- *   and output.  Exporting mmfd library to js might also be nice perhaps,
- *   either as alternative or addition.
- * - mmap(2) - how could I do this without some byte class and associated
- *   methods?  Seems way tricky.
- * - lstat(2), fstat(2)
- * - dup2()
- * - rename(2), unlink(2) etc would be useful, but we need another class
- *   for this (maybe a VFS static class?)  Maybe even something calling
- *   execve(2) and fork(2), those primitives... popen(3) also.
- * - Also opendir(3) and friends wrapper...
- */
-
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <poll.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-#include <js_fd.h>
-
-
-
-/* Utility macros */
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-/* Internal representation of FD object */
-typedef struct jsfd {
-       int     fd;
-       int     type;
-       union   {
-               struct {
-                       char                    *path;
-                       int                     flags;
-                       mode_t                  mode;
-               } file;
-               struct {
-                       int                     domain, type, protocol;
-                       struct sockaddr_in      caddr;
-               } socket;
-       } u;
-       /* For polling; Interesting events, and occurred events */
-       short   events, revents;
-       /* Last error for this descriptor */
-       int     error;
-} jsfd_t;
-
-enum jsfd_types {
-       /* Type */
-       JSFD_NONE =     0,              /* Initial */
-       JSFD_STD =      (1 << 1),
-       JSFD_FILE =     (1 << 2),
-       JSFD_SOCKET =   (1 << 3)
-};
-
-/* Used our fd_sm_poll() function */
-struct poll_fdsi {
-       char    *name;  /* Property name or NULL */
-       jsval   fdobj;  /* Pointer to FD object */
-       jsfd_t  *jsfd;  /* Pointer to FD object data */
-};
-
-struct poll_fds {
-       struct pollfd           *entries;       /* Passed to poll(2) */
-       struct poll_fdsi        *info;
-       int                     count, size;
-};
-
-/* Functions arguments types */
-enum jsarg_types {
-       JSAT_INTEGER = 1,
-       JSAT_DOUBLE,
-       JSAT_STRING,
-       JSAT_OBJECT
-};
-
-
-/* Prototypes */
-static JSBool  fd_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    fd_finalize(JSContext *, JSObject *);
-
-static JSBool  fd_getProperty(JSContext *, JSObject *, jsval, jsval *);
-static JSBool  fd_setProperty(JSContext *, JSObject *, jsval, jsval *);
-
-static JSBool  fd_m_open(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_set(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_close(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_truncate(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fd_m_put(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_get(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_socket(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_connect(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_bind(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_listen(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_accept(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_shutdown(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fd_m_setsockopt(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fd_m_getsockopt(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fd_m_fcntl(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_write(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_read(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_fdatasync(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  fd_m_lseek(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_fchmod(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_flock(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_m_fstat(JSContext *, JSObject *, uintN, jsval *, jsval *);
-
-static JSBool  fd_sm_poll(JSContext *, JSObject *, uintN, jsval *, jsval *);
-static JSBool  fd_sm_poll_mkset(JSContext *, jsval *, jsval *, void *);
-
-static JSBool  object_iterate(JSContext *, JSObject *, void *,
-                   JSBool (*)(JSContext *, jsval *, jsval *, void *));
-static int     fd_path_allow(const char *);
-static mode_t  fd_mode_allow(mode_t);
-static int     fd_flags_allow(int);
-static jsfd_t * fd_methods_args_check(JSContext *, JSObject *, const char *,
-                   int, int, jsval *, int);
-
-
-
-/* Actual class parameters */
-static JSClass fd_class = {
-       "FD", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       fd_getProperty, fd_setProperty, JS_EnumerateStub, JS_ResolveStub,
-       JS_ConvertStub, fd_finalize
-};
-
-enum fd_methods_args_enum {
-       FDMA_SET,
-       FDMA_CLOSE,
-       FDMA_TRUNCATE,
-       FDMA_GET,
-       FDMA_SOCKET,
-       FDMA_CONNECT,
-       FDMA_BIND,
-       FDMA_LISTEN,
-       FDMA_ACCEPT,
-       FDMA_SHUTDOWN,
-       FDMA_SETSOCKOPT,
-       FDMA_GETSOCKOPT,
-       FDMA_FCNTL,
-       FDMA_READ,
-       FDMA_WRITE,
-       FDMA_FDATASYNC,
-       FDMA_LSEEK,
-       FDMA_FCHMOD,
-       FDMA_FLOCK,
-       FDMA_FSTAT,
-       FDMA_MAX
-};
-
-static int fd_methods_args_array[FDMA_MAX][6] = {
-       { 1, JSAT_INTEGER },                            /* SET */
-       { 0 },                                          /* CLOSE */
-       { 1, JSAT_DOUBLE },                             /* TRUNCATE */
-       { 0 },                                          /* GET */
-       { 3, JSAT_INTEGER, JSAT_INTEGER, JSAT_INTEGER },/* SOCKET */
-       { 2, JSAT_STRING, JSAT_INTEGER },               /* CONNECT */
-       { 2, JSAT_STRING, JSAT_INTEGER },               /* BIND */
-       { 1, JSAT_INTEGER },                            /* LISTEN */
-       { 0 },                                          /* ACCEPT */
-       { 1, JSAT_INTEGER },                            /* SHUTDOWN */
-       { 2, JSAT_INTEGER, JSAT_INTEGER },              /* SETSOCKOPT */
-       { 1, JSAT_INTEGER },                            /* GETSOCKOPT */
-       { 2, JSAT_INTEGER, JSAT_INTEGER },              /* FCNTL */
-       { 1, JSAT_INTEGER },                            /* READ */
-       { 1, JSAT_STRING },                             /* WRITE */
-       { 0 },                                          /* FDATASYNC */
-       { 2, JSAT_DOUBLE, JSAT_INTEGER },               /* LSEEK */
-       { 1, JSAT_INTEGER },                            /* FCHMOD */
-       { 1, JSAT_INTEGER },                            /* FLOCK */
-       { 0 }                                           /* FSTAT */
-};
-
-/* Provided methods/functions */
-static JSFunctionSpec fd_methods[] = {
-       { "open", fd_m_open, 0, 0, 0 }, /* Variable 2-3 parameters */
-       { "set", fd_m_set, 1, 0, 0 },
-       { "close", fd_m_close, 0, 0, 0 },
-       { "truncate", fd_m_truncate, 1, 0, 0 },
-       { "put", fd_m_put, 1, 0, 0 },
-       { "get", fd_m_get, 0, 0, 0 },
-       { "socket", fd_m_socket, 3, 0, 0 },
-       { "connect", fd_m_connect, 2, 0, 0 },
-       { "bind", fd_m_bind, 2, 0, 0 },
-       { "listen", fd_m_listen, 1, 0, 0 },
-       { "accept", fd_m_accept, 0, 0, 0 },
-       { "shutdown", fd_m_shutdown, 1, 0, 0 },
-       { "setsockopt", fd_m_setsockopt, 2, 0, 0 },
-       { "getsockopt", fd_m_getsockopt, 1, 0, 0 },
-       { "fcntl", fd_m_fcntl, 2, 0, 0 },
-       { "read", fd_m_read, 1, 0, 0 },
-       { "write", fd_m_write, 1, 0, 0 },
-       { "fdatasync", fd_m_fdatasync, 0, 0, 0 },
-       { "lseek", fd_m_lseek, 2, 0, 0 },
-       { "fchmod", fd_m_fchmod, 1, 0, 0 },
-       { "flock", fd_m_flock, 1, 0, 0 },
-       { "fstat", fd_m_fstat, 0, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/* Provided static methods */
-static JSFunctionSpec fd_smethods[] = {
-       { "poll", fd_sm_poll, 2, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/* Provided properties */
-enum fd_props {
-       FD_P_PATH = 0,
-       FD_P_FD,
-       FD_P_MODE,
-       FD_P_EVENTS,
-       FD_P_REVENTS,
-       FD_P_ERRNO,
-       FD_P_CLIENT_ADDR,
-       FD_P_CLIENT_PORT,
-       FD_P_MAX
-};
-
-static JSPropertySpec fd_properties[FD_P_MAX + 1] = {
-       { "path", FD_P_PATH, JSPROP_ENUMERATE | JSPROP_READONLY, NULL, NULL },
-       { "fd", FD_P_FD, JSPROP_ENUMERATE | JSPROP_READONLY, NULL, NULL },
-       { "mode", FD_P_MODE, JSPROP_ENUMERATE | JSPROP_READONLY, NULL, NULL },
-       { "events", FD_P_EVENTS, JSPROP_ENUMERATE, NULL, NULL },
-       { "revents", FD_P_REVENTS, JSPROP_ENUMERATE | JSPROP_READONLY, NULL,
-           NULL },
-       { "errno", FD_P_ERRNO, JSPROP_ENUMERATE | JSPROP_READONLY, NULL,
-           NULL },
-       { "client_addr", FD_P_CLIENT_ADDR, JSPROP_ENUMERATE | JSPROP_READONLY,
-           NULL, NULL },
-       { "client_port", FD_P_CLIENT_PORT, JSPROP_ENUMERATE | JSPROP_READONLY,
-           NULL, NULL },
-       { NULL, 0, 0, NULL, NULL }
-};
-
-/*
- * Provided static properties.
- * We use these to provide ECMAScript with the ability to use system-specific
- * standard C constant macros without us having to tidiously map them
- * individually, or to require other scripts to be used as headers to define
- * them.  Another possibility would have been to supply these parameters as
- * string, but this would have required even slower remapping because of the
- * parsing and string comparisions.
- * We only include those which we consider necessary for now, others may be
- * added easily as needed, provided that they are added in all three maps.
- * I might perhaps develop macros and/or functions to map all these easily
- * from a single map.
- */
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-#define SP(n) \
-    { #n, n }
-
-static struct property_spec    fd_sprops[] = {
-       SP(STDIN_FILENO),
-       SP(STDOUT_FILENO),
-       SP(STDERR_FILENO),
-
-       SP(O_RDONLY),
-       SP(O_WRONLY),
-       SP(O_RDWR),
-       SP(O_APPEND),
-       SP(O_CREAT),
-       SP(O_TRUNC),
-       SP(O_NONBLOCK),
-
-       SP(POLLIN),
-       SP(POLLRDNORM),
-       SP(POLLRDBAND),
-       SP(POLLPRI),
-       SP(POLLOUT),
-       SP(POLLWRNORM),
-       SP(POLLWRBAND),
-       SP(POLLERR),
-       SP(POLLHUP),
-       SP(POLLNVAL),
-
-       SP(SHUT_RD),
-       SP(SHUT_WR),
-       SP(SHUT_RDWR),
-
-       SP(AF_INET),
-       SP(SOCK_STREAM),
-       SP(SOCK_DGRAM),
-
-       SP(SO_REUSEADDR),
-       SP(SO_REUSEPORT),
-       SP(SO_KEEPALIVE),
-       SP(SO_DONTROUTE),
-       SP(SO_LINGER),
-       SP(SO_BROADCAST),
-       SP(SO_OOBINLINE),
-       SP(SO_SNDBUF),
-       SP(SO_RCVBUF),
-       SP(SO_SNDLOWAT),
-       SP(SO_RCVLOWAT),
-       SP(SO_SNDTIMEO),
-       SP(SO_RCVTIMEO),
-       SP(SO_TIMESTAMP),
-       SP(SO_TYPE),
-       SP(SO_ERROR),
-       SP(TCP_NODELAY),
-
-       SP(F_SETFL),
-       SP(F_GETFL),
-
-       SP(SEEK_SET),
-       SP(SEEK_CUR),
-       SP(SEEK_END),
-
-       SP(S_IRWXU),
-       SP(S_IRUSR),
-       SP(S_IWUSR),
-       SP(S_IXUSR),
-       SP(S_IRWXG),
-       SP(S_IRGRP),
-       SP(S_IXGRP),
-       SP(S_IRWXO),
-       SP(S_IROTH),
-       SP(S_IWOTH),
-       SP(S_IXOTH),
-       SP(S_ISUID),
-       SP(S_ISGID),
-       SP(S_ISVTX),
-       SP(S_IFMT),
-       SP(S_IFIFO),
-       SP(S_IFCHR),
-       SP(S_IFDIR),
-       SP(S_IFBLK),
-       SP(S_IFREG),
-       SP(S_IFLNK),
-       SP(S_IFSOCK),
-       SP(S_IFWHT),
-       SP(UF_NODUMP),
-       SP(UF_IMMUTABLE),
-       SP(UF_APPEND),
-       SP(UF_OPAQUE),
-       SP(SF_ARCHIVED),
-       SP(SF_IMMUTABLE),
-       SP(SF_APPEND),
-
-       SP(LOCK_SH),
-       SP(LOCK_EX),
-       SP(LOCK_NB),
-       SP(LOCK_UN),
-
-       { NULL, 0 }
-};
-
-#undef SP
-
-
-
-/*
- * Miscelaneous static globals
- */
-
-/* XXX Should be initialized at main process startup ideally */
-static int     tcp_proto = -1;
-static char    *read_charbuf = NULL;
-static size_t  read_charbuf_size = 0;
-
-
-
-/*
- * Class control functions
- */
-
-JSObject *
-js_InitFDClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &fd_class, fd_constructor,
-           0, fd_properties, fd_methods, NULL, fd_smethods))
-           == NULL) {
-               (void) fprintf(stderr, "Error initializing FD class\n");
-               return NULL;
-       }
-
-       /* Create static properties.  Should probably be a function. */
-
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "FD: JS_GetConstructor == NULL\n");
-               return NULL;
-       }
-       for (sp = fd_sprops; sp->name != NULL; sp++) {
-               if (JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT) == JS_FALSE) {
-                       (void) fprintf(stderr,
-                           "FD: Error defining property %s\n", sp->name);
-                       return NULL;
-               }
-       }
-
-       return proto;
-}
-
-static JSBool
-fd_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t  *jsfd = NULL;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       /*
-        * IMPORTANT: We must verify if the caller attempts to execute us as a
-        * normal function rather than as a constructor.  Otherwise, the
-        * caller can cause the interpreter to abort(3) in an assertion in
-        * JS_SetPrivate()!
-        */
-       if (!JS_IsConstructing(cx)) {
-               QUEUE_EXCEPTION("Constructor called as a function");
-               goto err;
-       }
-
-       if ((jsfd = JS_malloc(cx, sizeof(jsfd_t))) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-
-       jsfd->fd = -1;
-       jsfd->type = JSFD_NONE;
-       jsfd->events = jsfd->revents = 0;
-       jsfd->error = 0;
-
-       if (!JS_SetPrivate(cx, obj, jsfd)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (jsfd != NULL)
-               JS_free(cx, jsfd);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-       return JS_FALSE;
-}
-
-static void
-fd_finalize(JSContext *cx, JSObject *obj)
-{
-       jsfd_t  *jsfd;
-
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL)) != NULL) {
-               /* Only close if not one of std descriptors */
-               if (jsfd->fd != -1 && jsfd->type != JSFD_STD) {
-                       (void) close(jsfd->fd);
-                       jsfd->fd = -1;
-                       jsfd->type = JSFD_NONE;
-               }
-               if (jsfd->type == JSFD_FILE && jsfd->u.file.path != NULL) {
-                       JS_free(cx, jsfd->u.file.path);
-                       jsfd->u.file.path = NULL;
-               }
-               JS_free(cx, jsfd);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-}
-
-
-/*
- * Property functions
- */
-
-static JSBool
-fd_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-       jsfd_t  *jsfd;
-       jsint   p;
-
-       if (!JSVAL_IS_INT(id))
-               return JS_TRUE;
-       p = (int)JSVAL_TO_INT(id);
-
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL)) == NULL)
-               return JS_TRUE;
-       if (jsfd->fd == -1)
-               return JS_TRUE;
-
-       switch (p) {
-       case FD_P_PATH:
-               if (jsfd->type == JSFD_FILE) {
-                       JSString        *string;
-
-                       if ((string = JS_NewStringCopyZ(cx,
-                           jsfd->u.file.path)) == NULL) {
-                               QUEUE_EXCEPTION("Out of memory");
-                               return JS_FALSE;
-                       }
-                       *vp = STRING_TO_JSVAL(string);
-               }
-               break;
-       case FD_P_FD:
-               *vp = INT_TO_JSVAL(jsfd->fd);
-               break;
-       case FD_P_MODE:
-               if (jsfd->type == JSFD_FILE)
-                       *vp = INT_TO_JSVAL((int)jsfd->u.file.mode);
-               break;
-       case FD_P_EVENTS:
-               *vp = INT_TO_JSVAL((int)jsfd->events);
-               break;
-       case FD_P_REVENTS:
-               *vp = INT_TO_JSVAL((int)jsfd->revents);
-               break;
-       case FD_P_ERRNO:
-               *vp = INT_TO_JSVAL(jsfd->error);
-               break;
-       case FD_P_CLIENT_ADDR:
-               if (jsfd->type == JSFD_SOCKET) {
-                       char            addr[16];
-                       JSString        *string;
-
-                       if (inet_ntop(AF_INET, &jsfd->u.socket.caddr.sin_addr,
-                           addr, 15) == NULL) {
-                               QUEUE_EXCEPTION(strerror(errno));
-                               return JS_FALSE;
-                       }
-                       if ((string = JS_NewStringCopyZ(cx, addr)) == NULL) {
-                               QUEUE_EXCEPTION("Out of memory");
-                               return JS_FALSE;
-                       }
-                       *vp = STRING_TO_JSVAL(string);
-               }
-               break;
-       case FD_P_CLIENT_PORT:
-               if (jsfd->type == JSFD_SOCKET) {
-                       *vp = INT_TO_JSVAL((int)ntohs(jsfd->
-                           u.socket.caddr.sin_port));
-               }
-               break;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-       jsfd_t  *jsfd;
-       jsint   p;
-
-       if (!JSVAL_IS_INT(id))
-               return JS_TRUE;
-       p = (int)JSVAL_TO_INT(id);
-
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL)) == NULL)
-               return JS_TRUE;
-       if (jsfd->fd == -1)
-               return JS_TRUE;
-
-       switch (p) {
-       case FD_P_EVENTS:
-               if (!JSVAL_IS_INT(*vp)) {
-                       QUEUE_EXCEPTION(
-                           "FD_P_EVENTS property requires an int");
-                       return JS_FALSE;
-               }
-               jsfd->events = (short)JSVAL_TO_INT(*vp);
-               break;
-       }
-
-       return JS_TRUE;
-}
-
-
-/*
- * Static properties functions
- */
-
-
-/*
- * Method functions
- */
-
-static JSBool
-fd_m_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       int             fd, flags;
-       mode_t          mode = 0644;
-       char            *bytes;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       /*
-        * We use custom arguments checking here since we can accept both
-        * 2 or 3.
-        */
-       if (argc < 2 || argc > 3) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("First argument must be a string");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Second argument must be an integer");
-               return JS_FALSE;
-       }
-       if (argc == 3 && !JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Third argument must be an integer");
-               return JS_FALSE;
-       }
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Null private data!");
-               return JS_FALSE;
-       }
-       if (jsfd->type != JSFD_NONE) {
-               QUEUE_EXCEPTION("Descriptor already open");
-               return JS_FALSE;
-       }
-
-       if (argc == 3) {
-               /*
-                * Mode, supplied as an int.
-                */
-               mode = (mode_t)JSVAL_TO_INT(argv[2]);
-               if ((mode = fd_mode_allow(mode)) == (mode_t)-1) {
-                       QUEUE_EXCEPTION("Mode not permitted");
-                       return JS_FALSE;
-               }
-       }
-
-       /*
-        * Flags, provided as an int.
-        */
-       flags = JSVAL_TO_INT(argv[1]);
-       if ((flags = fd_flags_allow(flags)) == -1) {
-               QUEUE_EXCEPTION("Flag not permitted");
-               return JS_FALSE;
-       }
-
-       /* Path, provided as a string */
-       if ((bytes = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-       /* Perform path sanity checking */
-       if (fd_path_allow(bytes) == -1) {
-               QUEUE_EXCEPTION("Invalid path");
-               return JS_FALSE;
-       }
-       if ((jsfd->u.file.path = JS_strdup(cx, bytes)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               return JS_FALSE;
-       }
-
-       /* We can finally attempt to open(2) */
-       if ((fd = open(bytes, flags, mode)) == -1) {
-               jsfd->error = errno;
-               /*
-                * XXX strerror() seems to always need to load up the
-                * nls table file, which is way silly for performance.
-                * This is related to locale stuff, and should be able
-                * to simply be disabled, even.
-                * Since this event occurs often in httpd.js, let's just
-                * output a fixed string for now.
-                * I should actually fix NetBSD libc on this matter.
-                */
-/*             QUEUE_EXCEPTION(strerror(errno));       */
-               QUEUE_EXCEPTION("open() error");
-               JS_free(cx, jsfd->u.file.path);
-               return JS_FALSE;
-       }
-
-       /* Success! */
-       jsfd->fd = fd;
-       jsfd->type = JSFD_FILE;
-       jsfd->u.file.flags = flags;
-       jsfd->u.file.mode = mode;
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_set(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       int32_t         fd;
-       jsfd_t          *jsfd;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "set", FDMA_SET, argc,
-           argv, JSFD_NONE)) == NULL)
-               return JS_FALSE;
-
-       fd = JSVAL_TO_INT(*argv);
-       if (fd < STDIN_FILENO || fd > STDERR_FILENO) {
-               QUEUE_EXCEPTION("Unknown standard descriptor");
-               return JS_FALSE;
-       }
-       jsfd->fd = fd;
-       jsfd->type = JSFD_STD;
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t  *jsfd;
-       int     error;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "close", FDMA_CLOSE, argc,
-           argv, JSFD_STD | JSFD_FILE | JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       if (jsfd->type == JSFD_STD) {
-               jsfd->fd = -1;
-               jsfd->type = JSFD_NONE;
-               return JS_TRUE;
-       }
-
-       if (jsfd->type == JSFD_FILE) {
-               if (jsfd->u.file.path != NULL) {
-                       JS_free(cx, jsfd->u.file.path);
-                       jsfd->u.file.path = NULL;
-               }
-       }
-
-       error = close(jsfd->fd);
-       jsfd->fd = -1;
-       jsfd->type = JSFD_NONE;
-
-       if (error == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_truncate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t          *jsfd;
-       off_t           size;
-       jsdouble        dsize;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "truncate", FDMA_TRUNCATE,
-           argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       if (!JS_ValueToNumber(cx, *argv, &dsize)) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-       size = (off_t)dsize;
-
-       if (ftruncate(jsfd->fd, size) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_put(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       JSString        *str;
-       char            *bytes;
-       ssize_t         size;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Null private data!");
-               return JS_FALSE;
-       }
-
-       if (jsfd->fd == -1) {
-               QUEUE_EXCEPTION("Descriptor closed");
-               return JS_FALSE;
-       }
-
-       /*
-        * Instead of verifying if supplied value really is a JSString, and
-        * using JSVAL_TO_STRING(), we convert the value to a string in this
-        * case.
-        */
-       if ((str = JS_ValueToString(cx, *argv)) == NULL ||
-           (bytes = JS_GetStringBytes(str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-
-       size = strlen(bytes);
-       if ((size = write(jsfd->fd, bytes, size)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       *rval = INT_TO_JSVAL((int)size);
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_get(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       char            bytes[4096];
-       ssize_t         size;
-       JSString        *string;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "get", FDMA_GET, argc,
-           argv, JSFD_STD | JSFD_FILE | JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       if ((size = read(jsfd->fd, bytes, 4096)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-       if (size == 0)
-               return JS_TRUE;
-
-       if ((string = JS_NewStringCopyN(cx, bytes, size)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(string);
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_socket(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       int     domain, type, protocol, error;
-       jsfd_t  *jsfd;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "socket", FDMA_SOCKET,
-           argc, argv, JSFD_NONE)) == NULL)
-               return JS_FALSE;
-
-       domain = (int)JSVAL_TO_INT(argv[0]);
-       type = (int)JSVAL_TO_INT(argv[1]);
-       protocol = (int)JSVAL_TO_INT(argv[2]);
-
-       /* Sanity checking on currently supported protocols */
-       if (domain != AF_INET || (type != SOCK_DGRAM && type != SOCK_STREAM)
-           || protocol != 0) {
-               QUEUE_EXCEPTION("Unsupported protocol");
-               return JS_FALSE;
-       }
-
-       if ((error = socket(domain, type, protocol)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       jsfd->fd = error;
-       jsfd->type = JSFD_SOCKET;
-       jsfd->u.socket.domain = domain;
-       jsfd->u.socket.type = type;
-       jsfd->u.socket.protocol = protocol;
-
-       return JS_TRUE;
-}
-
-/*
- * We currently make this rather simple; If the supplied string doesn't
- * consist of a valid IPv4 address, we simply attempt to resolve it, and on
- * success then attempt connection.
- */
-static JSBool
-fd_m_connect(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t                  *jsfd;
-       char                    *address;
-       struct sockaddr_in      sinaddr;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "connect", FDMA_CONNECT,
-           argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       address = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-       if (inet_pton(AF_INET, address, &sinaddr.sin_addr) != 1) {
-               struct hostent  *h;
-
-               /*
-                * Not a valid IPv4 address, consider it as a hostname and
-                * attempt to resolve it.
-                * XXX Note: Not thread safe unless a global mutex/rwlock is
-                * used.  Should use getaddrinfo(3) instead.  Especially if we
-                * someday want to support other address families than
-                * AF_INET.
-                */
-               if ((h = gethostbyname(address)) == NULL) {
-                       jsfd->error = errno;
-                       QUEUE_EXCEPTION("Invalid address or hostname");
-                       return JS_FALSE;
-               }
-               sinaddr.sin_addr.s_addr =
-                   ((struct in_addr *)h->h_addr_list[0])->s_addr;
-       }
-       sinaddr.sin_port = htons((in_port_t)JSVAL_TO_INT(argv[1]));
-
-       if (connect(jsfd->fd, (struct sockaddr *)&sinaddr,
-           sizeof(struct sockaddr_in)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_bind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t                  *jsfd;
-       struct sockaddr_in      sinaddr;
-       char                    *address;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "bind", FDMA_BIND, argc,
-           argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       address = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-       if (inet_pton(AF_INET, address, &sinaddr.sin_addr) != 1) {
-               QUEUE_EXCEPTION("Invalid IP address");
-               return JS_FALSE;
-       }
-       sinaddr.sin_port = htons((in_port_t)JSVAL_TO_INT(argv[1]));
-
-       if (bind(jsfd->fd, (struct sockaddr *)&sinaddr,
-           sizeof(struct sockaddr_in)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_listen(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t  *jsfd;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "listen", FDMA_LISTEN,
-           argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       if (listen(jsfd->fd, (int)JSVAL_TO_INT(*argv)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_accept(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t                  *jsfd, *njsfd;
-       int                     sock;
-       struct sockaddr_in      sinaddr;
-       socklen_t               socklen;
-       JSObject                *nobj;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "accept", FDMA_ACCEPT,
-           argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       socklen = sizeof(struct sockaddr_in);
-       if ((sock = accept(jsfd->fd, (struct sockaddr *)&sinaddr, &socklen))
-           == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       /*
-        * Success, create new FD object, fill it and return it.
-        */
-       if ((nobj = JS_ConstructObject(cx, &fd_class, obj, obj)) == NULL) {
-               (void) close(sock);
-               QUEUE_EXCEPTION("Out of resources");
-               return JS_FALSE;
-       }
-       njsfd = JS_GetInstancePrivate(cx, nobj, &fd_class, NULL);
-       njsfd->fd = sock;
-       njsfd->type = JSFD_SOCKET;
-       njsfd->u.socket.domain = jsfd->u.socket.domain;
-       njsfd->u.socket.type = jsfd->u.socket.type;
-       njsfd->u.socket.protocol = jsfd->u.socket.protocol;
-       (void) memcpy(&njsfd->u.socket.caddr, &sinaddr,
-           sizeof(struct sockaddr_in));
-
-       *rval = OBJECT_TO_JSVAL(nobj);
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_shutdown(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t  *jsfd;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "shutdown", FDMA_SHUTDOWN,
-           argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       if (shutdown(jsfd->fd, (int)JSVAL_TO_INT(*argv)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-/*
- * XXX Not thread safe ATM as it uses a static int with test-and-set operation
- * to only query the protocol database once.  This could be done at early
- * process initialization alternatively.
- * Unlike BSD/POSIX setsockopt(2), always requires a single integer value (-1
- * in the case of SO_LINGER to disable it, or the number of seconds to
- * linger to enable it).
- */
-static JSBool
-fd_m_setsockopt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t          *jsfd;
-       void            *opt;
-       struct linger   l;
-       int             optname, level, optval;
-       socklen_t       optlen;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "setsockopt",
-           FDMA_SETSOCKOPT, argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       optname = JSVAL_TO_INT(argv[0]);
-       optval = JSVAL_TO_INT(argv[1]);
-
-       /*
-        * Work out special case for SO_LINGER
-        */
-       if (optname == SO_LINGER) {
-               if (optval == -1) {
-                       l.l_onoff = 0;
-                       l.l_linger = 0;
-               } else {
-                       l.l_onoff = 1;
-                       l.l_linger = optval;
-               }
-               opt = &l;
-               optlen = sizeof(struct linger);
-       } else {
-               opt = &optval;
-               optlen = sizeof(int);
-               optval = (optval != 0 ? 1 : 0);
-       }
-
-       /*
-        * And for TCP_NODELAY which must use tcp_proto as level
-        */
-       if (optname == TCP_NODELAY) {
-               if (tcp_proto == -1) {
-                       struct protoent *pent;
-
-                       if ((pent = getprotobyname("TCP")) != NULL)
-                               tcp_proto = pent->p_proto;
-                       else
-                               tcp_proto = 4;  /* Generally allright */
-               }
-               level = tcp_proto;
-       } else
-               level = SOL_SOCKET;
-
-       if (setsockopt(jsfd->fd, level, optname, opt, optlen) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-/*
- * XXX Not thread safe ATM as it uses a static int with test-and-set operation
- * to only query the protocol database once.  This could be done at early
- * process initialization alternatively.
- * Unlike BSD/POSIX getsockopt(2), always returns a single integer value (-1
- * in the case of SO_LINGER disabled, or the number of seconds assigned to
- * wait if enabled).
- */
-static JSBool
-fd_m_getsockopt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t          *jsfd;
-       void            *opt;
-       struct linger   l;
-       int             i, optname, level, result;
-       socklen_t       optlen;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "getsockopt",
-           FDMA_GETSOCKOPT, argc, argv, JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       optname = JSVAL_TO_INT(*argv);
-
-       /*
-        * Special case for SO_LINGER which expects a structure rather than an
-        * integer
-        */
-       if (optname == SO_LINGER) {
-               opt = &l;
-               optlen = sizeof(struct linger);
-       } else {
-               opt = &i;
-               optlen = sizeof(int);
-       }
-
-       /*
-        * And for TCP_NODELAY which must use TCP protocol number rather than
-        * SOL_SOCKET level
-        */
-       if (optname == TCP_NODELAY) {
-               if (tcp_proto == -1) {
-                       struct protoent *pent;
-
-                       if ((pent = getprotobyname("TCP")) != NULL)
-                               tcp_proto = pent->p_proto;
-                       else
-                               tcp_proto = 4;  /* Generally allright */
-               }
-               level = tcp_proto;
-       } else
-               level = SOL_SOCKET;
-
-       if (getsockopt(jsfd->fd, level, optname, opt, &optlen) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       /*
-        * To simplify the implementation, special case of SO_LINGER result;
-        * We return -1 if lingering is disabled, or otherwise return the
-        * number of seconds it should linger for maximum.
-        */
-       if (optname == SO_LINGER) {
-               if (l.l_onoff != 0)
-                       result = l.l_linger;
-               else
-                       result = -1;
-       } else
-               /*
-                * These are booleans, so ensure proper return value despite
-                * several implementations which return a mask rather than 0/1
-                */
-               result = (i != 0 ? 1 : 0);
-
-       *rval = INT_TO_JSVAL(result);
-
-       return JS_TRUE;
-}
-
-/*
- * Unlike POSIX fcntl(2), only currently supports F_GETFL and F_SETFL along
- * with O_NONBLOCK and O_APPEND.  The flags argument is also mandatory, which
- * will serve as a result mask for F_GETFL or to set wanted flags using
- * F_SETFL.  The previous flags are returned as usual (but will only ever
- * include 0, O_NONBLOCK and/or O_APPEND).
- */
-static JSBool
-fd_m_fcntl(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t  *jsfd;
-       int     cmd, flags, error;
-
-       *rval = INT_TO_JSVAL(0);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "fcntl", FDMA_FCNTL,
-           argc, argv, JSFD_FILE | JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       cmd = JSVAL_TO_INT(argv[0]);
-       flags = JSVAL_TO_INT(argv[1]);
-
-       if (cmd != F_GETFL && cmd != F_SETFL) {
-               QUEUE_EXCEPTION("Unimplemented fcntl() command");
-               return JS_FALSE;
-       }
-       flags &= (O_NONBLOCK | O_APPEND);
-       if ((flags & O_NONBLOCK) == 0 && (flags & O_APPEND) == 0) {
-               QUEUE_EXCEPTION("Unimplemented fcntl() flag");
-               return JS_FALSE;
-       }
-
-       if (cmd == F_GETFL) {
-               if ((error = fcntl(jsfd->fd, cmd, NULL)) == -1) {
-                       jsfd->error = errno;
-                       QUEUE_EXCEPTION(strerror(errno));
-                       return JS_FALSE;
-               }
-               error &= flags;
-       } else {
-               if ((error = fcntl(jsfd->fd, cmd, flags)) == -1) {
-                       jsfd->error = errno;
-                       QUEUE_EXCEPTION(strerror(errno));
-                       return JS_FALSE;
-               }
-               error &= (O_NONBLOCK | O_APPEND);
-       }
-
-       *rval = INT_TO_JSVAL(error);
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       size_t          size;
-       ssize_t         rsize;
-       JSString        *string;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "read", FDMA_READ,
-           argc, argv, JSFD_FILE | JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       size = (size_t)JSVAL_TO_INT(*argv);
-       if (size < 1) {
-               QUEUE_EXCEPTION("read() requested size smaller than 1");
-               return JS_FALSE;
-       }
-
-       /*
-        * Ensure that our read buffer is ready, and of a large enough size
-        * to accomodate read.
-        */
-       if (read_charbuf_size < size) {
-               if (read_charbuf == NULL) {
-                       /* Never allocated yet, simply allocate */
-                       if ((read_charbuf = malloc(size)) == NULL) {
-                               QUEUE_EXCEPTION("Cannot allocate read buffer");
-                               return JS_FALSE;
-                       }
-               } else {
-                       char    *ptr;
-
-                       /* Buffer too small, attempt to increase it */
-                       if ((ptr = realloc(read_charbuf, size)) == NULL) {
-                               QUEUE_EXCEPTION(
-                                   "Cannot reallocate read buffer");
-                               return JS_FALSE;
-                       }
-                       read_charbuf = ptr;
-               }
-               read_charbuf_size = size;
-       }
-
-       if ((rsize = read(jsfd->fd, read_charbuf, size)) == -1) {
-               /*
-                * XXX Should we really throw an exception, or simply return
-                * an error?  For instance, if using nonblocking mode and
-                * expecting EAGAIN, would using an exception clubber
-                * unnecessarily the code?
-                */
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-       if (size == 0)
-               return JS_TRUE;
-
-       if ((string = JS_NewStringCopyN(cx, read_charbuf, rsize)) == NULL) {
-               QUEUE_EXCEPTION("Couldn't allocate read result string");
-               return JS_FALSE;
-       }
-       *rval = STRING_TO_JSVAL(string);
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       ssize_t         rsize;
-       JSString        *str;
-       char            *bytes;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "write", FDMA_WRITE,
-           argc, argv, JSFD_FILE | JSFD_SOCKET)) == NULL)
-               return JS_FALSE;
-
-       str = JSVAL_TO_STRING(*argv);
-       if ((bytes = JS_GetStringBytes(str)) == NULL) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-
-       if ((rsize = write(jsfd->fd, bytes, JS_GetStringLength(str))) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-       *rval = INT_TO_JSVAL((int)rsize);
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_fdatasync(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       jsfd_t          *jsfd;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "fdatasync",
-           FDMA_FDATASYNC, argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       if (fdatasync(jsfd->fd) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_lseek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       off_t           off, newoff;
-       int             whence;
-       jsdouble        doff;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "lseek", FDMA_LSEEK,
-           argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       if (!JS_ValueToNumber(cx, argv[0], &doff)) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-       off = (off_t)doff;
-       whence = JSVAL_TO_INT(argv[1]);
-
-       if ((newoff = lseek(jsfd->fd, off, whence)) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       if (!JS_NewDoubleValue(cx, (jsdouble)newoff, rval)) {
-               QUEUE_EXCEPTION("Internal error");
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_fchmod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       mode_t          mode;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "fchmod", FDMA_FCHMOD,
-           argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       mode = (mode_t)JSVAL_TO_INT(*argv);
-       if ((mode = fd_mode_allow(mode)) == (mode_t)-1) {
-               QUEUE_EXCEPTION("Mode not permitted");
-               return JS_FALSE;
-       }
-
-       if (fchmod(jsfd->fd, mode) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_flock(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       int             op;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "flock", FDMA_FLOCK,
-           argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       op = JSVAL_TO_INT(*argv);
-       if (flock(jsfd->fd, op) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       return JS_TRUE;
-}
-
-static JSBool
-fd_m_fstat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       jsfd_t          *jsfd;
-       struct stat     st;
-       JSObject        *array = NULL;
-       jsval           val;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if ((jsfd = fd_methods_args_check(cx, obj, "fstat", FDMA_FSTAT,
-           argc, argv, JSFD_FILE)) == NULL)
-               return JS_FALSE;
-
-       if (fstat(jsfd->fd, &st) == -1) {
-               jsfd->error = errno;
-               QUEUE_EXCEPTION(strerror(errno));
-               return JS_FALSE;
-       }
-
-       /*
-        * Note: We immediately link newly created objects to avoid GC
-        * problems.  For the simplicity of this task we don't need an
-        * additional root to be created using JS_AddRoot(), since *rval
-        * is already rooted.  Moreover, the double objects we create are
-        * immediately added as propery as well.
-        */
-
-       if ((array = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(array);
-
-#define DEFINE_INT_PROP(n, i)  do {                                    \
-       val = INT_TO_JSVAL((int)(i));                                   \
-       if (!JS_DefineProperty(cx, array, (n), val, NULL, NULL,         \
-           JSPROP_ENUMERATE)) {                                        \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-#define DEFINE_DOUBLE_PROP(n, d) do {                                  \
-       if (!JS_NewDoubleValue(cx, (jsdouble)(d), &val))                \
-               goto err;                                               \
-       if (!JS_DefineProperty(cx, array, (n), val, NULL, NULL,         \
-           JSPROP_ENUMERATE)) {                                        \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-       DEFINE_INT_PROP("st_dev", st.st_dev);
-       DEFINE_INT_PROP("st_ino", st.st_ino);
-       DEFINE_INT_PROP("st_mode", st.st_mode);
-       DEFINE_INT_PROP("st_nlink", st.st_nlink);
-       DEFINE_INT_PROP("st_uid", st.st_uid);
-       DEFINE_INT_PROP("st_gid", st.st_gid);
-       DEFINE_INT_PROP("st_rdev", st.st_rdev);
-       DEFINE_DOUBLE_PROP("st_atime", st.st_atime);
-       DEFINE_DOUBLE_PROP("st_mtime", st.st_mtime);
-       DEFINE_DOUBLE_PROP("st_ctime", st.st_ctime);
-       DEFINE_DOUBLE_PROP("st_size", st.st_size);
-       DEFINE_DOUBLE_PROP("st_blocks", st.st_blocks);
-       DEFINE_INT_PROP("st_blksize", st.st_blksize);
-       DEFINE_INT_PROP("st_flags", st.st_flags);
-       DEFINE_INT_PROP("st_gen", st.st_gen);
-
-#undef DEFINE_INT_PROP
-#undef DEFINE_DOUBLE_PROP
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-
-
-/*
- * Static methods
- */
-
-static JSBool
-fd_sm_poll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-       struct poll_fds fds;
-       int             nfds, timeout, i;
-       JSObject        *array = NULL;
-       jsint           index;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       /*
-        * First make sure that user supplied object really consists of an
-        * array.
-        */
-       if (!JSVAL_IS_OBJECT(argv[0]) ||
-           !JS_IsArrayObject(cx, JSVAL_TO_OBJECT(argv[0]))) {
-               QUEUE_EXCEPTION("First argument must be Array object");
-               return JS_FALSE;
-       }
-
-       /*
-        * Obtain timeout from argv[1]
-        */
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Second argument must be timeout integer");
-               return JS_FALSE;
-       }
-       timeout = (int)JSVAL_TO_INT(argv[1]);
-
-       /*
-        * Create our pollfd array, iterating through all FD objects of the
-        * user-provided array object.
-        */
-       if ((fds.entries = malloc(sizeof(struct pollfd) * 16)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       if ((fds.info = malloc(sizeof(struct poll_fdsi) * 16)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       fds.count = 0;
-       fds.size = 16;
-       if (!object_iterate(cx, JSVAL_TO_OBJECT(argv[0]), &fds,
-           fd_sm_poll_mkset))
-               goto err;
-
-       /*
-        * Finally perform actual polling
-        */
-       if ((nfds = poll(fds.entries, fds.count, timeout)) == -1) {
-               QUEUE_EXCEPTION(strerror(errno));
-               goto err;
-       }
-
-       /*
-        * Now set FD objects event field and create custom array object to
-        * return to the caller, only holding entries for which events
-        * occurred.
-        * Link object immediately to avoid GC problems or needing
-        * JS_AddRoot().
-        */
-       if ((array = JS_NewArrayObject(cx, 0, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       *rval = OBJECT_TO_JSVAL(array);
-
-       for (i = 0, index = 0; i < fds.count && nfds != 0; i++) {
-               if (fds.entries[i].revents != 0) {
-                       nfds--;
-                       fds.info[i].jsfd->revents = fds.entries[i].revents;
-                       /*
-                        * Add an element if numeric index entry, or a
-                        * property if name based/associative entry.
-                        */
-                       if (fds.info[i].name == NULL) {
-                               if (!JS_DefineElement(cx, array, index++,
-                                   fds.info[i].fdobj, NULL, NULL,
-                                   JSPROP_ENUMERATE)) {
-                                       QUEUE_EXCEPTION("Internal error!");
-                                       goto err;
-                               }
-                       } else {
-                               if (!JS_DefineProperty(cx, array,
-                                   fds.info[i].name, fds.info[i].fdobj, NULL,
-                                   NULL, JSPROP_ENUMERATE)) {
-                                       QUEUE_EXCEPTION("Internal error!");
-                                       goto err;
-                               }
-                       }
-               }
-       }
-
-       free(fds.entries);
-       free(fds.info);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (fds.entries != NULL)
-               free(fds.entries);
-       if (fds.info != NULL)
-               free(fds.info);
-
-       return JS_FALSE;
-}
-
-static JSBool
-fd_sm_poll_mkset(JSContext *cx, jsval *id, jsval *val, void *udata)
-{
-       struct poll_fds *fds = (struct poll_fds *)udata;
-       JSObject        *o;
-       jsfd_t          *jsfd;
-
-       if (!JSVAL_IS_OBJECT(*val) ||
-           !JS_InstanceOf(cx, (o = JSVAL_TO_OBJECT(*val)), &fd_class, NULL)) {
-               QUEUE_EXCEPTION("Not FD object");
-               return JS_FALSE;
-       }
-       if ((jsfd = JS_GetInstancePrivate(cx, o, &fd_class, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Null private data!");
-               return JS_FALSE;
-       }
-
-       if (fds->count == fds->size) {
-               void    *ptr;
-
-               /* Need to grow entries and names */
-               if ((ptr = realloc(fds->entries,
-                   sizeof(struct pollfd) * fds->size * 2)) == NULL) {
-                       QUEUE_EXCEPTION("Out of memory");
-                       return JS_FALSE;
-               }
-               fds->entries = ptr;
-               if ((ptr = realloc(fds->info,
-                   sizeof(struct poll_fdsi) * fds->size * 2)) == NULL) {
-                       QUEUE_EXCEPTION("Out of memory");
-                       return JS_FALSE;
-               }
-               fds->info = ptr;
-               fds->size *= 2;
-       }
-
-       /*
-        * Add new entry.  If it's a property (associative array entry), also
-        * fill in the name pointer which will be used to recreate the result
-        * array with those names as well.  We set the name to NULL for index
-        * based array entries.
-        */
-       fds->entries[fds->count].fd = jsfd->fd;
-       fds->entries[fds->count].events = jsfd->events;
-       fds->entries[fds->count].revents = 0;
-       if (JSVAL_IS_STRING(*id))
-               fds->info[fds->count].name =
-                  JS_GetStringBytes(JSVAL_TO_STRING(*id));
-       else
-               fds->info[fds->count].name = NULL;
-       fds->info[fds->count].fdobj = *val;
-       fds->info[fds->count++].jsfd = jsfd;
-
-       return JS_TRUE;
-}
-
-
-/*
- * Utility functions
- */
-
-/*
- * Was written to be able to iterate over all elements of an array object,
- * despite being an associated array or not, or a mix of both.  Unfortunately
- * uses marked as private JSIdArray structure.
- * This was needed because arrays are using indexes, while associative arrays
- * are nothing more than an object with its properties.  This function can
- * deal with both.
- */
-static JSBool
-object_iterate(JSContext *cx, JSObject *obj, void *udata,
-    JSBool (*func)(JSContext *, jsval *, jsval *, void *))
-{
-       JSIdArray       *a;
-       jsval           id, val;
-       char            *name;
-       jsint           i;
-       JSBool          ret = JS_FALSE;
-
-       if ((a = JS_Enumerate(cx, obj)) != NULL) {
-               for (i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JSVAL_IS_STRING(id)) {
-                               /*
-                                * Property id is a string, attempt to
-                                * lookup its value by name.
-                                */
-                               name = JS_GetStringBytes(JSVAL_TO_STRING(id));
-                               if (!JS_LookupProperty(cx, obj, name, &val))
-                                       continue;
-                       } else {
-                               /*
-                                * Property id is a number, attempt to
-                                * lookup its array element by index.
-                                */
-                               if (!JS_LookupElement(cx, obj,
-                                   JSVAL_TO_INT(id), &val))
-                                               continue;
-                       }
-                       if (!JSVAL_IS_VOID(val)) {
-                               if (!(ret = func(cx, &id, &val, udata)))
-                                       break;
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-       }
-
-       return ret;
-}
-
-/*
- * Utility function return 0 if user supplied path should be allowed, or -1 if
- * it should be rejected (invalid, or permission denied).  This can for
- * instance be used to restrict the program in a virtual chroot(2)-like jail.
- */
-/* ARGSUSED */
-static int
-fd_path_allow(const char *path)
-{
-       /* XXX */
-
-       return 0;
-}
-
-/* ARGSUSED */
-static mode_t
-fd_mode_allow(mode_t mode)
-{
-       /* XXX */
-
-       return mode;
-}
-
-/* ARGSUSED */
-static int
-fd_flags_allow(int flags)
-{
-       /* XXX */
-
-       return flags;
-}
-
-/*
- * Useful to ensure that a function's arguments are as expected, and to
- * retrieve the private data associated with the FD object.  Implemented to
- * minimize code duplication among common functions.
- */
-static jsfd_t *
-fd_methods_args_check(JSContext *cx, JSObject *obj, const char *fun, int id,
-    int argc, jsval *argv, int type)
-{
-       int     *p = fd_methods_args_array[id], i;
-       char    line[1024];
-       jsfd_t  *jsfd;
-
-       if (*p != argc) {
-               (void) snprintf(line, 1023,
-                   "%s() - Wrong number of arguments (%d), expected %d",
-                   fun, argc, *p);
-               QUEUE_EXCEPTION(line);
-               return NULL;
-       }
-
-       for (p++, i = 0; i < argc; i++) {
-               switch (p[i]) {
-               case JSAT_INTEGER:
-                       if (!JSVAL_IS_INT(argv[i])) {
-                               (void) snprintf(line, 1023,
-                                   "%s() - argument #%d not an integer",
-                                   fun, i + 1);
-                               QUEUE_EXCEPTION(line);
-                               return NULL;
-                       }
-                       break;
-               case JSAT_DOUBLE:
-                       if (!JSVAL_IS_DOUBLE(argv[i]) &&
-                           !JSVAL_IS_INT(argv[i])) {
-                               (void) snprintf(line, 1023,
-                                   "%s() - argument #%d not a double",
-                                   fun, i + 1);
-                               QUEUE_EXCEPTION(line);
-                               return NULL;
-                       }
-                       break;
-               case JSAT_STRING:
-                       if (!JSVAL_IS_STRING(argv[i])) {
-                               (void) snprintf(line, 1023,
-                                   "%s() - argument #%d not a string",
-                                   fun, i + 1);
-                               QUEUE_EXCEPTION(line);
-                               return NULL;
-                       }
-                       break;
-               default:
-                       (void) snprintf(line, 1023,
-                           "%s() - Unexpected argument type #%d",
-                           fun, i + 1);
-                       QUEUE_EXCEPTION(line);
-                       return NULL;
-               }
-       }
-
-       if ((jsfd = JS_GetInstancePrivate(cx, obj, &fd_class, NULL))
-           == NULL) {
-               (void) snprintf(line, 1023, "%s() - NULL private data!", fun);
-               QUEUE_EXCEPTION(line);
-               return NULL;
-       }
-
-       if (type == JSFD_NONE && jsfd->type != JSFD_NONE) {
-               (void) snprintf(line, 1023,
-                   "%s() - Descriptor is already open",
-                   fun);
-               QUEUE_EXCEPTION(line);
-               return NULL;
-       } else 
-               return jsfd;
-
-       if ((jsfd->type & type) == 0) {
-               (void) snprintf(line, 1023,
-                   "%s() - Descriptor is closed or of wrong type",
-                   fun);
-               QUEUE_EXCEPTION(line);
-               return NULL;
-       }
-
-       return jsfd;
-}
diff --git a/tests/js-test/src/classes/js_fd.h b/tests/js-test/src/classes/js_fd.h
deleted file mode 100644 (file)
index 9ef410e..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id: js_fd.h,v 1.4 2006/07/11 06:45:14 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSFD_H
-#define JSFD_H
-
-#include <jsapi.h>
-
-extern JSObject        *js_InitFDClass(JSContext *, JSObject *);
-
-#endif
diff --git a/tests/js-test/src/classes/js_global.c b/tests/js-test/src/classes/js_global.c
deleted file mode 100644 (file)
index c386b11..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/* $Id: js_global.c,v 1.1 2006/07/22 03:43:09 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Provide a means to set and access global objects and global properties.
- * Basically we can store hashtable objects, which each can store arbitrary
- * String/String tuples, but using shared memory instead of a database.
- * Internally a hash table would also be used to index hash tables by String.
- * There would be a single synchronization lock around the system.
- * We would need to initially work with an allocated buffer of shared memory,
- * which only needed pages are used.  For this, mmpool(3) could be used.
- * A pool of hash tables would be necessary, as well as one for the data
- * pair items.  To be linked among those.
- *
- * I yet have to find a proper interface.  We optionally could have stuff
- * like:
- *
- * Global.getProperty(table, property);
- * Global.setProperty(table, property, string);
- *
- * But would it also be possible to use lazy allocation such that this would
- * be possible, although of course enforcing the same internal behavior:
- *
- * Global.table.property  would be read or set as necessary.
- *
- * Or:
- * table = new Global(tablename);
- * table.prop = 'string';
- * out.put(table.prop + "\n");
- */
-
-
-
-#include <stdint.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-#include <js_global.h>
-
-
-
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-
-/*
- * Static prototypes
- */
-static JSBool  global_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    global_finalize(JSContext *, JSObject *);
-
-static JSBool  global_getProperty(JSContext *, JSObject *, jsval, jsval *);
-static JSBool  global_setProperty(JSContext *, JSObject *, jsval, jsval *);
-
-
-
-/*
- * Static globals
- */
-
-/* Global class */
-static JSClass pg_class = {
-       "Global", JCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       global_getProperty, global_setProperty, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, global_finalize
-};
-
-
-
-/*
- * Global object control
- */
-
-JSObject *
-js_InitGlobalClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &global_class,
-           global_constructor, 0, NULL, NULL, NULL, NULL)) == NULL) {
-               (void) fprintf(stderr, "Error initializing Global class\n");
-               goto err;
-       }
-
-       /* XXX Initialize shared memory and lock */
-
-       return proto;
-
-err:
-
-       return NULL;
-}
-
-static JSBool
-global_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       if (!JS_IsConstructing(cx)) {
-               QUEUE_EXCEPTION("Constructor called as a function");
-               goto err;
-       }
-
-       /* XXX */
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-global_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-
-       /* XXX */
-
-       return JS_TRUE;
-}
-
-static JSBool
-global_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
-{
-
-       /* XXX */
-
-       return JS_TRUE;
-}
diff --git a/tests/js-test/src/classes/js_global.h b/tests/js-test/src/classes/js_global.h
deleted file mode 100644 (file)
index 725ffea..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id: js_global.h,v 1.1 2006/07/22 03:43:09 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSGLOBAL_H
-#define JSGLOBAL_H
-
-#include <jsapi.h>
-
-extern JSObject        *js_InitGlobalClass(JSContext *, JSObject *);
-
-#endif
diff --git a/tests/js-test/src/classes/js_mysql.c b/tests/js-test/src/classes/js_mysql.c
deleted file mode 100644 (file)
index 8126f72..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-/* $Id: js_mysql.c,v 1.1 2006/07/09 00:30:30 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
diff --git a/tests/js-test/src/classes/js_mysql.h b/tests/js-test/src/classes/js_mysql.h
deleted file mode 100644 (file)
index c04eee4..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: js_mysql.h,v 1.1 2006/07/09 00:30:30 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSMYSQL_H
-#define JSMYSQL_H
-
-extern JSObject        *js_InitMySQLClass(JSContext *, JSObject *);
-
-#endif
diff --git a/tests/js-test/src/classes/js_pgsql.c b/tests/js-test/src/classes/js_pgsql.c
deleted file mode 100644 (file)
index e697b99..0000000
+++ /dev/null
@@ -1,3493 +0,0 @@
-/* $Id: js_pgsql.c,v 1.17 2006/07/22 03:22:05 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * XXX TODO XXX
- * - Verify if JS_GetStringLength() really safe to continue using
- * - Perhaps provide simpler replacement functions for query functions
- *   allowing separate parameters to be set (perhaps not necessary considering
- *   that we can provide null to an array).
- * - All functions creating doubles or strings should check if NULL is
- *   returned.  Verify this.
- * - (maybe) make reentrant by causing optimization buffers to be part of
- *   generated objects instances's private data (using structures as necessary
- *   instead of simply wrapping around the native object's pointer
- *   (actually PGconn object).
- * - 28.10. Notice Processing
- *   Either place one(s) that use syslog(3) transparently, or somehow allow
- *   the user to set a custom handler
- * - Large objects API
- * - Compare to PHP library to verify if missing any nice functions ideas
- * - See what to do about the following functions:
- *   - PQgetssl() (returns an SSL object!)
- *   - PQprint() (writes to a supplied FILE *)
- */
-
-
-
-#include <stdint.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-#include <libpq-fe.h>
-
-#include <js_pgsql.h>
-
-
-
-/*
- * PostgreSQL services for ECMAScript
- *
- * NOTES:
- * We create a parent PG object which allows us to store static first-level
- * methods as well as numeric properties required to work with the libpq
- * library.  Almost all other functionality is available through PGconn and
- * PGresult objects afterwards.
- *
- * If supporting the asynchroneous part of the API, it should also be possible
- * for us to return an FD object for a PGconn * so that polling could be used,
- * etc.  Or at least just return the fd int which can be used easily to create
- * an FD object with afterwards by the caller.
- */
-
-
-
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-
-
-/*
- * Static prototypes
- */
-static int     buffer_grow(size_t);
-static int     param_grow(int);
-
-static JSBool  pg_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSBool  pg_sm_PQconndefaults(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pg_sm_PQconnectdb(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pg_sm_PQconnectStart(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pg_sm_PQresStatus(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pg_sm_PQunescapeBytea(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSObject        *js_InitPGconnClass(JSContext *, JSObject *);
-static JSBool  pgconn_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    pgconn_finalize(JSContext *, JSObject *);
-
-static JSBool  pgconn_m_PQfinish(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQconnectPoll(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQreset(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQresetStart(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQresetPoll(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQdb(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQuser(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQpass(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQhost(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQport(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQtty(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQoptions(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQstatus(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQtransactionStatus(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQparameterStatus(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQprotocolVersion(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQserverVersion(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQerrorMessage(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQsocket(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQbackendPID(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQexec(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQsendQuery(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQexecParams2(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, int);
-static JSBool  pgconn_m_PQexecParams(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQsendQueryParams(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQprepare2(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *, int);
-static JSBool  pgconn_m_PQprepare(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQsendPrepare(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQexecPrepared2(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *, int);
-static JSBool  pgconn_m_PQexecPrepared(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQsendQueryPrepared(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQmakeEmptyPGresult(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQescapeStringConn(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQescapeByteaConn(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQgetCancel(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQnotifies(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQgetResult(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQconsumeInput(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQisBusy(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQsetnonblocking(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQisnonblocking(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQflush(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQsetErrorVerbosity(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgconn_m_PQtrace(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQuntrace(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQputCopyData(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQputCopyEnd(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgconn_m_PQgetCopyData(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSObject        *js_InitPGresultClass(JSContext *, JSObject *);
-static JSBool  pgresult_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    pgresult_finalize(JSContext *, JSObject *);
-
-static JSBool  pgresult_m_PQclear(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQresultStatus(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgresult_m_PQresultErrorMessage(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgresult_m_PQresultErrorField(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgresult_m_PQntuples(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQnfields(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQfname(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQfnumber(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQftable(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQftablecol(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQfformat(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQftype(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQfmod(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQfsize(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQbinaryTuples(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgresult_m_PQgetvalue(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQgetisnull(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQgetlength(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQcmdStatus(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQcmdTuples(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static JSBool  pgresult_m_PQoidValue(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-static JSObject        *js_InitPGcancelClass(JSContext *, JSObject *);
-static JSBool  pgcancel_constructor(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-static void    pgcancel_finalize(JSContext *, JSObject *);
-
-static JSBool  pgcancel_m_PQfreeCancel(JSContext *, JSObject *, uintN,
-                   jsval *, jsval *);
-static JSBool  pgcancel_m_PQcancel(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-
-
-/*
- * Static globals
- */
-
-/*
- * General purpose string buffer (note that this is not thread-safe).
- * Allows to optimize functions such as PQescapeStringConn().
- */
-static char    *buffer = NULL;
-static size_t  buffer_size = 0;
-static Oid     *param_types = NULL;
-static char    **param_values = NULL;
-static int     *param_lengths = NULL;
-static int     *param_formats = NULL;
-static int     param_entries = 0;
-
-/* PG class */
-static JSClass pg_class = {
-       "PG", 0, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,
-       JS_ConvertStub, JS_FinalizeStub
-};
-
-/* Provided static methods */
-static JSFunctionSpec pg_smethods[] = {
-       { "connDefaults", pg_sm_PQconndefaults, 0, 0, 0 },
-       { "connectDb", pg_sm_PQconnectdb, 1, 0, 0 },
-       { "connectStart", pg_sm_PQconnectStart, 1, 0, 0 },
-       { "resStatus", pg_sm_PQresStatus, 1, 0, 0 },
-       { "unescapeBytea", pg_sm_PQunescapeBytea, 2, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/* Provided static properties */
-
-#define SP(n) \
-    { #n, n }
-
-static struct property_spec    pg_sprops[] = {
-       SP(PGRES_POLLING_OK),
-       SP(PGRES_POLLING_READING),
-       SP(PGRES_POLLING_WRITING),
-       SP(PGRES_POLLING_FAILED),
-       SP(PGRES_EMPTY_QUERY),
-       SP(PGRES_COMMAND_OK),
-       SP(PGRES_TUPLES_OK),
-       SP(PGRES_COPY_OUT),
-       SP(PGRES_COPY_IN),
-       SP(PGRES_BAD_RESPONSE),
-       SP(PGRES_NONFATAL_ERROR),
-       SP(PGRES_FATAL_ERROR),
-       SP(PG_DIAG_SEVERITY),
-       SP(PG_DIAG_SQLSTATE),
-       SP(PG_DIAG_MESSAGE_PRIMARY),
-       SP(PG_DIAG_MESSAGE_DETAIL),
-       SP(PG_DIAG_MESSAGE_HINT),
-       SP(PG_DIAG_STATEMENT_POSITION),
-       SP(PG_DIAG_INTERNAL_POSITION),
-       SP(PG_DIAG_INTERNAL_QUERY),
-       SP(PG_DIAG_CONTEXT),
-       SP(PG_DIAG_SOURCE_FILE),
-       SP(PG_DIAG_SOURCE_LINE),
-       SP(PG_DIAG_SOURCE_FUNCTION),
-       SP(CONNECTION_OK),
-       SP(CONNECTION_BAD),
-       SP(CONNECTION_STARTED),
-       SP(CONNECTION_MADE),
-       SP(CONNECTION_AWAITING_RESPONSE),
-       SP(CONNECTION_AUTH_OK),
-       SP(CONNECTION_SSL_STARTUP),
-       SP(CONNECTION_SETENV),
-       SP(PQTRANS_IDLE),
-       SP(PQTRANS_ACTIVE),
-       SP(PQTRANS_INTRANS),
-       SP(PQTRANS_INERROR),
-       SP(PQTRANS_UNKNOWN),
-       SP(InvalidOid),
-       SP(PQERRORS_TERSE),
-       SP(PQERRORS_DEFAULT),
-       SP(PQERRORS_VERBOSE),
-       { NULL, 0 }
-};
-
-#undef SP
-
-
-/* PGconn class */
-static JSClass pgconn_class = {
-       "PGConn", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, pgconn_finalize
-};
-
-/* Provided methods/functions */
-static JSFunctionSpec pgconn_methods[] = {
-       { "finish", pgconn_m_PQfinish, 0, 0, 0 },
-       { "connectPoll", pgconn_m_PQconnectPoll, 0, 0, 0 },
-       { "reset", pgconn_m_PQreset, 0, 0, 0 },
-       { "resetStart", pgconn_m_PQresetStart, 0, 0, 0 },
-       { "resetPoll", pgconn_m_PQresetPoll, 0, 0, 0 },
-       { "db", pgconn_m_PQdb, 0, 0, 0 },
-       { "user", pgconn_m_PQuser, 0, 0, 0 },
-       { "pass", pgconn_m_PQpass, 0, 0, 0 },
-       { "host", pgconn_m_PQhost, 0, 0, 0 },
-       { "port", pgconn_m_PQport, 0, 0, 0 },
-       { "tty", pgconn_m_PQtty, 0, 0, 0 },
-       { "options", pgconn_m_PQoptions, 0, 0, 0 },
-       { "status", pgconn_m_PQstatus, 0, 0, 0 },
-       { "transactionStatus", pgconn_m_PQtransactionStatus, 0, 0, 0 },
-       { "parameterStatus", pgconn_m_PQparameterStatus, 1, 0, 0 },
-       { "protocolVersion", pgconn_m_PQprotocolVersion, 0, 0, 0 },
-       { "serverVersion", pgconn_m_PQserverVersion, 0, 0, 0 },
-       { "errorMessage", pgconn_m_PQerrorMessage, 0, 0, 0 },
-       { "socket", pgconn_m_PQsocket, 0, 0, 0 },
-       { "backendPid", pgconn_m_PQbackendPID, 0, 0, 0 },
-       { "exec", pgconn_m_PQexec, 1, 0, 0 },
-       { "sendQuery", pgconn_m_PQsendQuery, 1, 0, 0 },
-       { "execParams", pgconn_m_PQexecParams, 7, 0, 0 },
-       { "sendQueryParams", pgconn_m_PQsendQueryParams, 7, 0, 0 },
-       { "prepare", pgconn_m_PQprepare, 4, 0, 0 },
-       { "sendPrepare", pgconn_m_PQsendPrepare, 4, 0, 0 },
-       { "execPrepared", pgconn_m_PQexecPrepared, 6, 0, 0 },
-       { "sendQueryPrepared", pgconn_m_PQsendQueryPrepared, 6, 0, 0 },
-       { "makeEmptyPGResult", pgconn_m_PQmakeEmptyPGresult, 1, 0, 0 },
-       { "escapeStringConn", pgconn_m_PQescapeStringConn, 1, 0, 0 },
-       { "escapeByteaConn", pgconn_m_PQescapeByteaConn, 1, 0, 0 },
-       { "getCancel", pgconn_m_PQgetCancel, 0, 0, 0 },
-       { "notifies", pgconn_m_PQnotifies, 0, 0, 0 },
-       { "getResult", pgconn_m_PQgetResult, 0, 0, 0 },
-       { "consumeInput", pgconn_m_PQconsumeInput, 0, 0, 0 },
-       { "isBusy", pgconn_m_PQisBusy, 0, 0, 0 },
-       { "setNonBlocking", pgconn_m_PQsetnonblocking, 1, 0, 0 },
-       { "isNonBlocking", pgconn_m_PQisnonblocking, 0, 0, 0 },
-       { "flush", pgconn_m_PQflush, 0, 0, 0 },
-       { "setErrorVerbosity", pgconn_m_PQsetErrorVerbosity, 1, 0, 0 },
-       { "trace", pgconn_m_PQtrace, 0, 0, 0 },
-       { "untrace", pgconn_m_PQuntrace, 0, 0, 0 },
-       { "putCopyData", pgconn_m_PQputCopyData, 1, 0, 0 },
-       { "putCopyEnd", pgconn_m_PQputCopyEnd, 1, 0, 0 },
-       { "getCopyData", pgconn_m_PQgetCopyData, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-
-/* PGresult class */
-static JSClass pgresult_class = {
-       "PGResult", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, pgresult_finalize
-};
-
-/* Provided methods/functions */
-static JSFunctionSpec pgresult_methods[] = {
-       { "clear", pgresult_m_PQclear, 0, 0, 0 },
-       { "resultStatus", pgresult_m_PQresultStatus, 0, 0, 0 },
-       { "resultErrorMessage", pgresult_m_PQresultErrorMessage, 0, 0, 0 },
-       { "resultErrorField", pgresult_m_PQresultErrorField, 1, 0, 0 },
-       { "nTuples", pgresult_m_PQntuples, 0, 0, 0 },
-       { "nFields", pgresult_m_PQnfields, 0, 0, 0 },
-       { "fName", pgresult_m_PQfname, 1, 0, 0 },
-       { "fNumber", pgresult_m_PQfnumber, 1, 0, 0 },
-       { "fTable", pgresult_m_PQftable, 1, 0, 0 },
-       { "fTableCol", pgresult_m_PQftablecol, 1, 0, 0 },
-       { "fFormat", pgresult_m_PQfformat, 1, 0, 0 },
-       { "fType", pgresult_m_PQftype, 1, 0, 0 },
-       { "fMod", pgresult_m_PQfmod, 1, 0, 0 },
-       { "fSize", pgresult_m_PQfsize, 1, 0, 0 },
-       { "binaryTuples", pgresult_m_PQbinaryTuples, 1, 0, 0 },
-       { "getValue", pgresult_m_PQgetvalue, 2, 0, 0 },
-       { "getIsNull", pgresult_m_PQgetisnull, 2, 0, 0 },
-       { "getLength", pgresult_m_PQgetlength, 2, 0, 0 },
-       { "cmdStatus", pgresult_m_PQcmdStatus, 0, 0, 0 },
-       { "cmdTuples", pgresult_m_PQcmdTuples, 0, 0, 0 },
-       { "oidValue", pgresult_m_PQoidValue, 0, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-
-/* PGcancel class */
-static JSClass pgcancel_class = {
-       "PGCancel", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, pgcancel_finalize
-};
-
-/* Provided methods/functions */
-static JSFunctionSpec pgcancel_methods[] = {
-       { "freeCancel", pgcancel_m_PQfreeCancel, 0, 0, 0 },
-       { "cancel", pgcancel_m_PQcancel, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-
-
-static int
-buffer_grow(size_t required)
-{
-       size_t  new;
-       void    *ptr;
-
-       if (required <= buffer_size)
-               return 0;
-
-       for (new = buffer_size; new < required; new *= 2) ;
-
-       if ((ptr = realloc(buffer, new)) == NULL)
-               return -1;
-
-       buffer = ptr;
-       buffer_size = new;
-
-       return 0;
-}
-
-static int
-param_grow(int required)
-{
-       int     new;
-       void    *types, *values, *lengths, *formats;
-
-       if (required <= param_entries)
-               return 0;
-
-       for (new = param_entries; new < required; new *= 2) ;
-
-       if ((types = realloc(param_types, sizeof(Oid) * new)) == NULL ||
-           (values = realloc(param_values, sizeof(char *) * new)) == NULL ||
-           (lengths = realloc(param_lengths, sizeof(int) * new)) == NULL ||
-           (formats = realloc(param_formats, sizeof(int) * new)) == NULL)
-               return -1;
-
-       param_types = types;
-       param_values = values;
-       param_lengths = lengths;
-       param_formats = formats;
-       param_entries = new;
-
-       return 0;
-}
-
-
-/*
- * PG object control
- */
-
-JSObject *
-js_InitPGClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &pg_class, pg_constructor, 0,
-           NULL, NULL, NULL, pg_smethods)) == NULL) {
-               (void) fprintf(stderr, "Error initializing PG class\n");
-               goto err;
-       }
-
-       /* Create static properties */
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "PG: JS_GetConstructor == NULL\n");
-               goto err;
-       }
-       for (sp = pg_sprops; sp->name != NULL; sp++) {
-               if (!JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT)) {
-                       (void) fprintf(stderr,
-                           "PG: Error defining property %s\n", sp->name);
-                       goto err;
-               }
-       }
-
-       /* Initialize PGconn class since we'll need to instanciate it from C */
-       if (js_InitPGconnClass(cx, obj) == NULL) {
-               (void) fprintf(stderr, "PG: InitPGconnClass()\n");
-               goto err;
-       }
-       /* Same for PGresult class */
-       if (js_InitPGresultClass(cx, obj) == NULL) {
-               (void) fprintf(stderr, "PG: InitPGresultClass()\n");
-               goto err;
-       }
-       /* And PGcancel class */
-       if (js_InitPGcancelClass(cx, obj) == NULL) {
-               (void) fprintf(stderr, "PG: InitPGcancelClass()\n");
-               goto err;
-       }
-
-       /*
-        * Note that the following buffers, although allowing optimizations,
-        * cause the functions using them to not be reentrant.  For reentrancy
-        * similar buffers could be attached to the object instances instead.
-        * This would of course however mean a larger memory footprint.
-        * If doing this, we would also need a custom structure for the
-        * private data instead of simply wrapping around the native pointers.
-        */
-
-       /* Allocate an initial general purpose buffer */
-       if ((buffer = malloc(16384)) == NULL) {
-               (void) fprintf(stderr, "PG: malloc()\n");
-               goto err;
-       }
-       buffer_size = 16384;
-
-       /* As well as buffers for the *Params() parameter arrays */
-       if ((param_types = malloc(sizeof(Oid) * 16)) == NULL ||
-           (param_values = malloc(sizeof(char *) * 16)) == NULL ||
-           (param_lengths = malloc(sizeof(int) * 16)) == NULL ||
-           (param_formats = malloc(sizeof(int) * 16)) == NULL) {
-               (void) fprintf(stderr, "PG: malloc()\n");
-               goto err;
-       }
-       param_entries = 16;
-
-       return proto;
-
-err:
-       if (buffer != NULL)
-               free(buffer);
-       if (param_types != NULL)
-               free(param_types);
-       if (param_values != NULL)
-               free(param_values);
-       if (param_lengths != NULL)
-               free(param_lengths);
-       if (param_formats != NULL)
-               free(param_formats);
-
-       return NULL;
-}
-
-/* Non instanciable */
-static JSBool
-pg_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("PG class uninstanciable");
-
-       return JS_FALSE;
-}
-
-
-/*
- * PG object static methods
- */
-
-/*
- * Returns an array of objects which each contain the various parameters
- * returned by PQconndefaults().
- * XXX Could be more useful if it returned an object of objects using the
- * keyword as property in the first object level, perhaps.
- */
-static JSBool
-pg_sm_PQconndefaults(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PQconninfoOption        *in = NULL, *p;
-       JSObject                *array = NULL;
-       JSString                *str;
-       int                     i;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-
-       if ((in = PQconndefaults()) == NULL) {
-               QUEUE_EXCEPTION("PQconndefaults() == NULL");
-               goto err;
-       }
-       if ((array = JS_NewArrayObject(cx, 0, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(array);
-
-#define DEFINE_STRING_PROP(n, s)       do {                            \
-       if ((str = JS_NewStringCopyZ(cx, (char *)(s))) == NULL) {       \
-               QUEUE_EXCEPTION("Out of memory!");                      \
-               goto err;                                               \
-       }                                                               \
-       if (!JS_DefineProperty(cx, o, (n), STRING_TO_JSVAL(str), NULL,  \
-           NULL, JSPROP_ENUMERATE)) {                                  \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-#define DEFINE_STRING_PROP2(n, s, l)   do {                            \
-       if ((str = JS_NewStringCopyN(cx, (char *)(s), (l))) == NULL) {  \
-               QUEUE_EXCEPTION("Out of memory!");                      \
-               goto err;                                               \
-       }                                                               \
-       if (!JS_DefineProperty(cx, o, (n), STRING_TO_JSVAL(str), NULL,  \
-           NULL, JSPROP_ENUMERATE)) {                                  \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-#define DEFINE_INT_PROP(n, i)  do {                                    \
-       if (!JS_DefineProperty(cx, array, (n), INT_TO_JSVAL((int)(i)),  \
-           NULL, NULL, JSPROP_ENUMERATE)) {                            \
-               QUEUE_EXCEPTION("Internal error!");                     \
-               goto err;                                               \
-       }                                                               \
-} while (/* CONSTCOND */0)
-
-
-       /* Polulate array with objects */
-       for (i = 0, p = in; p->keyword != NULL; p++, i++) {
-               JSObject        *o;
-
-               if ((o = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
-                       QUEUE_EXCEPTION("Out of memory");
-                       goto err;
-               }
-               /* Root immediately by inserting object into array */
-               if (!JS_DefineElement(cx, array, i, OBJECT_TO_JSVAL(o),
-                   NULL, NULL, JSPROP_ENUMERATE)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-
-               /* Populate object with properties */
-               DEFINE_STRING_PROP("keyword", p->keyword);
-               DEFINE_STRING_PROP("envvar", p->envvar);
-               DEFINE_STRING_PROP("compiled", p->compiled);
-               DEFINE_STRING_PROP("val", p->val);
-               DEFINE_STRING_PROP("label", p->label);
-               DEFINE_STRING_PROP2("dispchar", p->dispchar, 1);
-               DEFINE_INT_PROP("dispsize", p->dispsize);
-       }
-
-#undef DEFINE_STRING_PROP
-#undef DEFINE_STRING_PROP2
-#undef DEFINE_INT_PROP
-
-       PQconninfoFree(in);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-       if (in != NULL)
-               PQconninfoFree(in);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pg_sm_PQconnectdb(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc = NULL;
-       char            *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-       str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-
-       if ((o = JS_NewObject(cx, &pgconn_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if ((pgc = PQconnectdb(str)) == NULL) {
-               QUEUE_EXCEPTION("PQconnectdb");
-               goto err;
-       }
-       if (!JS_SetPrivate(cx, o, pgc)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgc != NULL)
-               PQfinish(pgc);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pg_sm_PQconnectStart(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc = NULL;
-       char            *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-       str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-
-       if ((o = JS_NewObject(cx, &pgconn_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if ((pgc = PQconnectStart(str)) == NULL) {
-               QUEUE_EXCEPTION("PQconnectStart");
-               goto err;
-       }
-       if (!JS_SetPrivate(cx, o, pgc)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgc != NULL)
-               PQfinish(pgc);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pg_sm_PQresStatus(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       char    *res;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       res = PQresStatus(JSVAL_TO_INT(argv[0]));
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, res));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: Semantics are different from C PQunescapeBytea() in that it is
- * supplied a single String and that it returns a resulting String, or null on
- * error.  Much easier to work with within ECMAScript this way.
- */
-static JSBool
-pg_sm_PQunescapeBytea(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       JSString        *str;
-       char            *from;
-       size_t          reslen;
-       unsigned char   *res = NULL;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       from = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-
-       if ((res = PQunescapeBytea(from, &reslen)) == NULL) {
-               QUEUE_EXCEPTION("PQescapeByteaConn()");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, res, reslen)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       PQfreemem(res);
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       if (res != NULL)
-               PQfreemem(res);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-
-/*
- * PGconn object control
- */
-
-static JSObject *
-js_InitPGconnClass(JSContext *cx, JSObject *obj)
-{
-
-       return (JS_InitClass(cx, obj, NULL, &pgconn_class, pgconn_constructor,
-           0, NULL, pgconn_methods, NULL, NULL));
-}
-
-/* Non instanciable */
-static JSBool
-pgconn_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("PGconn class not user-instanciable");
-
-       return JS_FALSE;
-}
-
-static void
-pgconn_finalize(JSContext *cx, JSObject *obj)
-{
-       PGconn  *pgc;
-
-       if ((pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL))
-           != NULL) {
-               PQfinish(pgc);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-}
-
-
-/*
- * PGconn object methods
- */
-
-static JSBool
-pgconn_m_PQfinish(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       if ((pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL))
-           != NULL) {
-               PQfinish(pgc);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQconnectPoll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn                          *pgc;
-       PostgresPollingStatusType       s;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       s = PQconnectPoll(pgc);
-       *rval = INT_TO_JSVAL((int)s);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQreset(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn                          *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       PQreset(pgc);
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQresetStart(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQconnectPoll(pgc));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQresetPoll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn                          *pgc;
-       PostgresPollingStatusType       s;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       s = PQresetPoll(pgc);
-       *rval = INT_TO_JSVAL((int)s);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQdb(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       char    *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQdb(pgc);
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQuser(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       char    *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQuser(pgc);
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQpass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       char    *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQpass(pgc);
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQhost(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       char    *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQhost(pgc);
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       char    *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQport(pgc);
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQtty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       char    *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQtty(pgc);
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQoptions(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       char    *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQoptions(pgc);
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQstatus(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       ConnStatusType  s = CONNECTION_BAD;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       s = PQstatus(pgc);
-       *rval = INT_TO_JSVAL((int)s);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQtransactionStatus(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn                  *pgc;
-       PGTransactionStatusType s;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       s = PQtransactionStatus(pgc);
-       *rval = INT_TO_JSVAL((int)s);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQparameterStatus(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn          *pgc;
-       char            *param;
-       const char      *str;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               return JS_FALSE;
-       }
-       param = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((str = PQparameterStatus(pgc, param)) != NULL)
-               *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQprotocolVersion(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn  *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQprotocolVersion(pgc));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQserverVersion(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn  *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQserverVersion(pgc));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQerrorMessage(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-       char    *str;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = PQerrorMessage(pgc);
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQsocket(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQsocket(pgc));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQbackendPID(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn  *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQbackendPID(pgc));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQexec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-       char            *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-       str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if ((pgr = PQexec(pgc, str)) == NULL) {
-               QUEUE_EXCEPTION("PQexec()");
-               goto err;
-       }
-       if (!JS_SetPrivate(cx, o, pgr)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQsendQuery(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       char            *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-       str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQsendQuery(pgc, str));
-
-       return JS_TRUE;
-
-err:
-       *rval = INT_TO_JSVAL(0);
-
-       return JS_FALSE;
-}
-
-/*
- * A fairly hairy function.
- */
-static JSBool
-pgconn_m_PQexecParams2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, int async)
-{
-       int             nargs, i;
-       JSObject        *arrays[4], *o;
-       JSIdArray       *a = NULL;
-       Oid             *types = NULL;
-       char            **values = NULL;
-       int             *lengths = NULL;
-       int             *formats = NULL;
-       char            str[256];
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-
-       if (argc != 7) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an int");
-               goto err;
-       }
-       for (i = 2; i < 6; i++) {
-               if (JSVAL_IS_NULL(argv[i])) {
-                       arrays[i - 2] = NULL;
-                       continue;
-               }
-               if (!JSVAL_IS_OBJECT(argv[i]) ||
-                   !JS_IsArrayObject(cx,
-                   (arrays[i - 2] = JSVAL_TO_OBJECT(argv[i])))) {
-                       (void) snprintf(str, 255, "Argument %d not an Array",
-                           i + 1);
-                       QUEUE_EXCEPTION(str);
-                       goto err;
-               }
-       }
-       if (!JSVAL_IS_INT(argv[6])) {
-               QUEUE_EXCEPTION("Argument 7 not an int");
-               goto err;
-       }
-
-       /* Array arguments processing */
-       nargs = JSVAL_TO_INT(argv[1]);
-       if (nargs < 0) {
-               QUEUE_EXCEPTION("Argument 2 negative");
-               goto err;
-       }
-
-       if (arrays[0] != NULL)
-               types = param_types;
-       if (arrays[1] != NULL)
-               values = param_values;
-       if (arrays[2] != NULL)
-               lengths = param_lengths;
-       if (arrays[3] != NULL)
-               formats = param_formats;
-
-       for (i = 0; i < 4; i++) {
-               jsint   len;
-
-               if (arrays[i] == NULL)
-                       continue;
-
-               if (!JS_GetArrayLength(cx, arrays[i], &len) || len != nargs) {
-                       (void) snprintf(str, 255,
-                           "Argument %d Array not holding %d elements",
-                           i + 2, nargs);
-                       QUEUE_EXCEPTION(str);
-                       goto err;
-               }
-       }
-
-       if (param_grow(nargs) == -1) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       /* param_types */
-       if (types != NULL) {
-               jsval           id, val;
-               int             i2;
-               jsdouble        v;
-
-               o = arrays[0];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_NUMBER(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 3 Array's element %d "
-                                           "not a number", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               if (!JS_ValueToNumber(cx, val, &v)) {
-                                       QUEUE_EXCEPTION("Internal error!");
-                                       goto err;
-                               }
-                               types[i2++] = (Oid)v;
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       /* param_values */
-       if (values != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[1];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (JSVAL_IS_NULL(val)) {
-                                       values[i2++] = NULL;
-                                       continue;
-                               }
-                               if (!JSVAL_IS_STRING(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 4 Array's element %d "
-                                           "not a String", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               values[i2++] = JS_GetStringBytes(
-                                   JSVAL_TO_STRING(val));
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       /* param_lengths */
-       if (lengths != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[2];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_INT(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 5 Array's element %d "
-                                           "not an int", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               lengths[i2++] = JSVAL_TO_INT(val);
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       /* param_formats */
-       if (formats != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[3];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_INT(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 6 Array's element %d "
-                                           "not an int", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               formats[i2++] = JSVAL_TO_INT(val);
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if (!async) {
-
-               if ((pgr = PQexecParams(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   nargs, types, (const char * const *)values, lengths,
-                   formats, JSVAL_TO_INT(argv[6]))) == NULL) {
-                       QUEUE_EXCEPTION("PQexecParams()");
-                       goto err;
-               }
-
-               if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               /* Root immediately */
-               *rval = OBJECT_TO_JSVAL(o);
-
-               if (!JS_SetPrivate(cx, o, pgr)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-
-       } else {
-
-               *rval = INT_TO_JSVAL(PQsendQueryParams(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   nargs, types, (const char * const *)values, lengths,
-                   formats, JSVAL_TO_INT(argv[6])));
-
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-       if (a != NULL)
-               JS_DestroyIdArray(cx, a);
-
-       if (!async)
-               *rval = OBJECT_TO_JSVAL(NULL);
-       else
-               *rval = INT_TO_JSVAL(0);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQexecParams(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return pgconn_m_PQexecParams2(cx, obj, argc, argv, rval, 0);
-}
-
-static JSBool
-pgconn_m_PQsendQueryParams(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return pgconn_m_PQexecParams2(cx, obj, argc, argv, rval, 1);
-}
-
-static JSBool
-pgconn_m_PQprepare2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, int async)
-{
-       int             nargs, i;
-       JSObject        *array, *o;
-       JSIdArray       *a = NULL;
-       Oid             *types = NULL;
-       char            str[256];
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-
-       if (argc != 4) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[2])) {
-               QUEUE_EXCEPTION("Argument 3 not an int");
-               goto err;
-       }
-       if (JSVAL_IS_NULL(argv[3]))
-               array = NULL;
-       else {
-               if (!JSVAL_IS_OBJECT(argv[3]) ||
-                   !JS_IsArrayObject(cx,
-                   (array = JSVAL_TO_OBJECT(argv[3])))) {
-                       QUEUE_EXCEPTION("Argument 4 not an Array");
-                       goto err;
-               }
-       }
-
-       /* Array arguments processing */
-       nargs = JSVAL_TO_INT(argv[2]);
-       if (nargs < 0) {
-               QUEUE_EXCEPTION("Argument 3 negative");
-               goto err;
-       }
-
-       if (array != NULL) {
-               jsint   len;
-
-               types = param_types;
-
-               if (!JS_GetArrayLength(cx, array, &len) || len != nargs) {
-                       (void) snprintf(str, 255,
-                           "Argument 4 Array not holding %d elements",
-                           nargs);
-                       QUEUE_EXCEPTION(str);
-                       goto err;
-               }
-       }
-
-       if (param_grow(nargs) == -1) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       /* param_types */
-       if (types != NULL) {
-               jsval           id, val;
-               int             i2;
-               jsdouble        v;
-
-               o = array;
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_NUMBER(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 4 Array's element %d "
-                                           "not a number", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               if (!JS_ValueToNumber(cx, val, &v)) {
-                                       QUEUE_EXCEPTION("Internal error!");
-                                       goto err;
-                               }
-                               types[i2++] = (Oid)v;
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if (!async) {
-
-               if ((pgr = PQprepare(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[1])),
-                   nargs, types)) == NULL) {
-                       QUEUE_EXCEPTION("PQprepare()");
-                       goto err;
-               }
-
-               if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               /* Root immediately */
-               *rval = OBJECT_TO_JSVAL(o);
-
-               if (!JS_SetPrivate(cx, o, pgr)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-
-       } else {
-
-               *rval = INT_TO_JSVAL(PQsendPrepare(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[1])),
-                   nargs, types));
-
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-
-       if (!async)
-               *rval = OBJECT_TO_JSVAL(NULL);
-       else
-               *rval = INT_TO_JSVAL(0);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQprepare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return pgconn_m_PQprepare2(cx, obj, argc, argv, rval, 0);
-}
-
-static JSBool
-pgconn_m_PQsendPrepare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return pgconn_m_PQprepare2(cx, obj, argc, argv, rval, 1);
-}
-
-/*
- * Also rather hairy
- */
-static JSBool
-pgconn_m_PQexecPrepared2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval, int async)
-{
-       int             nargs, i;
-       JSObject        *arrays[3], *o;
-       JSIdArray       *a = NULL;
-       char            **values = NULL;
-       int             *lengths = NULL;
-       int             *formats = NULL;
-       char            str[256];
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-
-       if (argc != 6) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an int");
-               goto err;
-       }
-       for (i = 2; i < 5; i++) {
-               if (JSVAL_IS_NULL(argv[i])) {
-                       arrays[i - 2] = NULL;
-                       continue;
-               }
-               if (!JSVAL_IS_OBJECT(argv[i]) ||
-                   !JS_IsArrayObject(cx,
-                   (arrays[i - 2] = JSVAL_TO_OBJECT(argv[i])))) {
-                       (void) snprintf(str, 255, "Argument %d not an Array",
-                           i + 1);
-                       QUEUE_EXCEPTION(str);
-                       goto err;
-               }
-       }
-       if (!JSVAL_IS_INT(argv[5])) {
-               QUEUE_EXCEPTION("Argument 7 not an int");
-               goto err;
-       }
-
-       /* Array arguments processing */
-       nargs = JSVAL_TO_INT(argv[1]);
-       if (nargs < 0) {
-               QUEUE_EXCEPTION("Argument 2 negative");
-               goto err;
-       }
-
-       if (arrays[0] != NULL)
-               values = param_values;
-       if (arrays[1] != NULL)
-               lengths = param_lengths;
-       if (arrays[2] != NULL)
-               formats = param_formats;
-
-       for (i = 0; i < 3; i++) {
-               jsint   len;
-
-               if (arrays[i] == NULL)
-                       continue;
-
-               if (!JS_GetArrayLength(cx, arrays[i], &len) || len != nargs) {
-                       (void) snprintf(str, 255,
-                           "Argument %d Array not holding %d elements",
-                           i + 2, nargs);
-                       QUEUE_EXCEPTION(str);
-                       goto err;
-               }
-       }
-
-       if (param_grow(nargs) == -1) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       /* param_values */
-       if (values != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[0];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (JSVAL_IS_NULL(val)) {
-                                       values[i2++] = NULL;
-                                       continue;
-                               }
-                               if (!JSVAL_IS_STRING(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 3 Array's element %d "
-                                           "not a String", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               values[i2++] = JS_GetStringBytes(
-                                   JSVAL_TO_STRING(val));
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       /* param_lengths */
-       if (lengths != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[1];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_INT(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 4 Array's element %d "
-                                           "not an int", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               lengths[i2++] = JSVAL_TO_INT(val);
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       /* param_formats */
-       if (formats != NULL) {
-               jsval           id, val;
-               int             i2;
-
-               o = arrays[2];
-               if ((a = JS_Enumerate(cx, o)) == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               for (i2 = i = 0; i < a->length; i++) {
-                       JS_IdToValue(cx, a->vector[i], &id);
-                       if (JS_LookupElement(cx, o, JSVAL_TO_INT(id), &val) &&
-                           !JSVAL_IS_VOID(val)) {
-                               if (!JSVAL_IS_INT(val)) {
-                                       (void) snprintf(str, 255,
-                                           "Argument 5 Array's element %d "
-                                           "not an int", i2);
-                                       QUEUE_EXCEPTION(str);
-                                       goto err;
-                               }
-                               formats[i2++] = JSVAL_TO_INT(val);
-                       }
-               }
-               JS_DestroyIdArray(cx, a);
-               a = NULL;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if (!async) {
-
-               if ((pgr = PQexecPrepared(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   nargs, (const char * const *)values, lengths, formats,
-                   JSVAL_TO_INT(argv[5]))) == NULL) {
-                       QUEUE_EXCEPTION("PQexecPrepared()");
-                       goto err;
-               }
-
-               if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               /* Root immediately */
-               *rval = OBJECT_TO_JSVAL(o);
-
-               if (!JS_SetPrivate(cx, o, pgr)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-
-       } else {
-
-               *rval = INT_TO_JSVAL(PQsendQueryPrepared(pgc,
-                   JS_GetStringBytes(JSVAL_TO_STRING(argv[0])),
-                   nargs, (const char * const *)values, lengths, formats,
-                   JSVAL_TO_INT(argv[5])));
-
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-       if (a != NULL)
-               JS_DestroyIdArray(cx, a);
-
-       if (!async)
-               *rval = OBJECT_TO_JSVAL(NULL);
-       else
-               *rval = INT_TO_JSVAL(0);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQexecPrepared(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       return pgconn_m_PQexecPrepared2(cx, obj, argc, argv, rval, 0);
-}
-
-static JSBool
-pgconn_m_PQsendQueryPrepared(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-
-       return pgconn_m_PQexecPrepared2(cx, obj, argc, argv, rval, 1);
-}
-
-static JSBool
-pgconn_m_PQmakeEmptyPGresult(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if ((pgr = PQmakeEmptyPGresult(pgc, JSVAL_TO_INT(argv[0]))) == NULL) {
-               QUEUE_EXCEPTION("PQmakeEmptyPGresult()");
-               goto err;
-       }
-
-       if (!JS_SetPrivate(cx, o, pgr)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: Semantics are different from C PQescapeStringConn() in that it is
- * supplied a single String and that it returns a resulting String, or null on
- * error.  Much easier to work with within ECMAScript this way.
- */
-static JSBool
-pgconn_m_PQescapeStringConn(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn          *pgc;
-       JSString        *str;
-       char            *from;
-       size_t          len;
-       int             ret;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = JSVAL_TO_STRING(argv[0]);
-       from = JS_GetStringBytes(str);
-       len = JS_GetStringLength(str);
-
-       if (buffer_grow((len * 2) + 2) == -1) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       len = PQescapeStringConn(pgc, buffer, from, len, &ret);
-       if (ret != 0) {
-               QUEUE_EXCEPTION("PQescapeStringConn()");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, buffer, len)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/* PQescapeString() deprecated in favor of PQescapeStringConn() */
-
-/*
- * Note: Semantics are different from C PQescapeByteaConn() in that it is
- * supplied a single String and that it returns a resulting String, or null on
- * error.  Much easier to work with within ECMAScript this way.
- */
-static JSBool
-pgconn_m_PQescapeByteaConn(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn          *pgc;
-       JSString        *str;
-       char            *from;
-       size_t          fromlen, reslen;
-       unsigned char   *res = NULL;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = JSVAL_TO_STRING(argv[0]);
-       from = JS_GetStringBytes(str);
-       fromlen = JS_GetStringLength(str);
-
-       if ((res = PQescapeByteaConn(pgc, from, fromlen, &reslen)) == NULL) {
-               QUEUE_EXCEPTION("PQescapeByteaConn()");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, res, reslen)) == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-
-       PQfreemem(res);
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       if (res != NULL)
-               PQfreemem(res);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQgetCancel(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       PGcancel        *pgcn = NULL;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((o = JS_NewObject(cx, &pgcancel_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if ((pgcn = PQgetCancel(pgc)) == NULL) {
-               QUEUE_EXCEPTION("PQgetCancel()");
-               goto err;
-       }
-       if (!JS_SetPrivate(cx, o, pgcn)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgcn != NULL)
-               PQfreeCancel(pgcn);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: Unlike C native PQnotifies(), returns null or a normal object with
- * the three properties set, rather than specifically a PQnotify object.
- */
-static JSBool
-pgconn_m_PQnotifies(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       PGnotify        *pgn = NULL;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((pgn = PQnotifies(pgc)) == NULL) {
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_TRUE;
-       }
-
-       if ((o = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if (!JS_DefineProperty(cx, o, "relname", STRING_TO_JSVAL(
-           JS_NewStringCopyZ(cx, pgn->relname)), NULL, NULL,
-           JSPROP_ENUMERATE)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       if (!JS_DefineProperty(cx, o, "be_pid", INT_TO_JSVAL(pgn->be_pid),
-           NULL, NULL, JSPROP_ENUMERATE)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       if (!JS_DefineProperty(cx, o, "extra", STRING_TO_JSVAL(
-           JS_NewStringCopyZ(cx, pgn->extra)), NULL, NULL,
-           JSPROP_ENUMERATE)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       PQfreemem(pgn);
-
-       return JS_TRUE;
-
-err:
-       if (pgn != NULL)
-               PQfreemem(pgn);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQgetResult(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       PGresult        *pgr = NULL;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       if ((pgr = PQgetResult(pgc)) == NULL) {
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_TRUE;
-       }
-
-       if ((o = JS_NewObject(cx, &pgresult_class, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if (!JS_SetPrivate(cx, o, pgr)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       if (pgr != NULL)
-               PQclear(pgr);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQconsumeInput(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQconsumeInput(pgc));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQisBusy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQisBusy(pgc));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQsetnonblocking(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn          *pgc;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQsetnonblocking(pgc, JSVAL_TO_INT(argv[0])));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQisnonblocking(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQisnonblocking(pgc));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQflush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQflush(pgc));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQsetErrorVerbosity(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGconn  *pgc;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQsetErrorVerbosity(pgc, JSVAL_TO_INT(argv[0])));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQtrace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-       PQtrace(pgc, stderr);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQuntrace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-       PQuntrace(pgc);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgconn_m_PQputCopyData(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-       JSString        *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       str = JSVAL_TO_STRING(argv[0]);
-       *rval = INT_TO_JSVAL(PQputCopyData(pgc, JS_GetStringBytes(str),
-           JS_GetStringLength(str)));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgconn_m_PQputCopyEnd(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGconn          *pgc;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0]) && !JSVAL_IS_NULL(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String or null");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       *rval = INT_TO_JSVAL(PQputCopyEnd(pgc, (JSVAL_IS_NULL(argv[0]) ? NULL :
-           JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: unlike native PQgetCopyData(), which returns an int but is supplied a
- * pointer to a pointer to be set, this implementation returns an object which
- * holds two elements: result (the integer) and data (null or String), to make
- * it easier to use with ECMAScript.
- */
-static JSBool
-pgconn_m_PQgetCopyData(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       JSObject        *o;
-       PGconn          *pgc;
-       char            *data = NULL;
-       int             res;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgconn_class, NULL);
-       assert(pgc != NULL);
-
-       res = PQgetCopyData(pgc, &data, JSVAL_TO_INT(argv[0]));
-
-       if ((o = JS_NewObject(cx, NULL, NULL, NULL)) == NULL) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       /* Root immediately */
-       *rval = OBJECT_TO_JSVAL(o);
-
-       if (!JS_DefineProperty(cx, o, "result", INT_TO_JSVAL(res),
-           NULL, NULL, JSPROP_ENUMERATE)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-       if (data != NULL && res > 0) {
-               if (!JS_DefineProperty(cx, o, "data", STRING_TO_JSVAL(
-                   JS_NewStringCopyN(cx, data, res)), NULL, NULL,
-                   JSPROP_ENUMERATE)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-               PQfreemem(data);
-       } else {
-               if (!JS_DefineProperty(cx, o, "data", OBJECT_TO_JSVAL(NULL),
-                   NULL, NULL, JSPROP_ENUMERATE)) {
-                       QUEUE_EXCEPTION("Internal error!");
-                       goto err;
-               }
-       }
-
-       return JS_TRUE;
-
-err:
-       if (data != NULL)
-               PQfreemem(data);
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-
-/*
- * PGresult object control
- */
-
-static JSObject *
-js_InitPGresultClass(JSContext *cx, JSObject *obj)
-{
-
-       return (JS_InitClass(cx, obj, NULL, &pgresult_class,
-           pgresult_constructor, 0, NULL, pgresult_methods, NULL, NULL));
-}
-
-/* Non instanciable */
-static JSBool
-pgresult_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("PGresult class not user-instanciable");
-
-       return JS_FALSE;
-}
-
-static void
-pgresult_finalize(JSContext *cx, JSObject *obj)
-{
-       PGresult        *pgr;
-
-       if ((pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL))
-           != NULL) {
-               PQclear(pgr);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-}
-
-
-/*
- * PGresult object methods
- */
-
-static JSBool
-pgresult_m_PQclear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       if ((pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL))
-           != NULL) {
-               PQclear(pgr);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgresult_m_PQresultStatus(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGresult        *pgr;
-       ExecStatusType  s;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       s = PQresultStatus(pgr);
-       *rval = INT_TO_JSVAL((int)s);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgresult_m_PQresultErrorMessage(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGresult        *pgr;
-       char            *res;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       res = PQresultErrorMessage(pgr);
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, res));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgresult_m_PQresultErrorField(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGresult        *pgr;
-       char            *res;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       res = PQresultErrorField(pgr, JSVAL_TO_INT(argv[0]));
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, res));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQntuples(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = INT_TO_JSVAL(PQntuples(pgr));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgresult_m_PQnfields(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = INT_TO_JSVAL(PQnfields(pgr));
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgresult_m_PQfname(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       char            *res;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       res = PQfname(pgr, JSVAL_TO_INT(argv[0]));
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, res));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQfnumber(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       char            *str;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument not a String");
-               goto err;
-       }
-       str = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = INT_TO_JSVAL(PQfnumber(pgr, str));
-
-       return JS_TRUE;
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: Oid is a typedef to unsigned int.  Thus, we use a double object to
- * make sure that we do not loose any precision.
- */
-static JSBool
-pgresult_m_PQftable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       Oid             oid;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       oid = PQftable(pgr, JSVAL_TO_INT(argv[0]));
-
-       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQftablecol(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = INT_TO_JSVAL(PQftablecol(pgr, JSVAL_TO_INT(argv[0])));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: we possibly could return a boolean value instead of an integer
- * but the documentation says that other values are reserved for possible
- * future use.  I am surprised that they do not return enumerated values.
- */
-static JSBool
-pgresult_m_PQfformat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = INT_TO_JSVAL(PQfformat(pgr, JSVAL_TO_INT(argv[0])));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: Oid is a typedef to unsigned int.  Thus, we use a double object to
- * make sure that we do not loose any precision.
- */
-static JSBool
-pgresult_m_PQftype(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       Oid             oid;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       oid = PQftype(pgr, JSVAL_TO_INT(argv[0]));
-
-       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQfmod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = INT_TO_JSVAL(PQfmod(pgr, JSVAL_TO_INT(argv[0])));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQfsize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = INT_TO_JSVAL(PQfsize(pgr, JSVAL_TO_INT(argv[0])));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQbinaryTuples(JSContext *cx, JSObject *obj, uintN argc,
-    jsval *argv, jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = INT_TO_JSVAL(PQbinaryTuples(pgr));
-
-       return JS_TRUE;
-}
-
-/*
- * Note: The semantics of PGresult.PQgetvalue() is different from the actual
- * libpq C function PQgetvalue() in that we return null on NULL fields, and
- * that we always return either the binary or text data into the field as a
- * String (since ECMAScript Strings objects allow NUL characters).
- */
-static JSBool
-pgresult_m_PQgetvalue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       JSString        *str;
-       char            *res;
-       int             row, col;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       row = JSVAL_TO_INT(argv[0]);
-       col = JSVAL_TO_INT(argv[1]);
-
-       if (PQgetisnull(pgr, row, col)) {
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_TRUE;
-       }
-
-       if ((res = PQgetvalue(pgr, row, col)) == NULL) {
-               QUEUE_EXCEPTION("PQgetvalue() == NULL");
-               goto err;
-       }
-
-       if ((str = JS_NewStringCopyN(cx, res, PQgetlength(pgr, row, col)))
-           == NULL) {
-               QUEUE_EXCEPTION("Out of memory!");
-               goto err;
-       }
-       *rval = STRING_TO_JSVAL(str);
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-/*
- * Note: unlike the C PQgetisnull() function, which returns 0 or 1, we return
- * true or false, since ECMAScript supports booleans.
- * Moreover, one no longer needs to call this function in JS if it is to
- * subsequently use PQgetvalue(), since ours can return null.
- * May still be useful in some situations.
- */
-static JSBool
-pgresult_m_PQgetisnull(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = BOOLEAN_TO_JSVAL(PQgetisnull(pgr, JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1])));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQgetlength(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 2) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not an int");
-               goto err;
-       }
-       if (!JSVAL_IS_INT(argv[1])) {
-               QUEUE_EXCEPTION("Argument 2 not an int");
-               goto err;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = INT_TO_JSVAL(PQgetlength(pgr, JSVAL_TO_INT(argv[0]),
-           JSVAL_TO_INT(argv[1])));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-static JSBool
-pgresult_m_PQcmdStatus(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, PQcmdStatus(pgr)));
-
-       return JS_TRUE;
-}
-
-/*
- * We could return a double easily, but like the C API are returning a string
- */
-static JSBool
-pgresult_m_PQcmdTuples(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, PQcmdTuples(pgr)));
-
-       return JS_TRUE;
-}
-
-/*
- * Note: Oid is a typedef to unsigned int.  Thus, we use a double object to
- * make sure that we do not loose any precision.
- */
-static JSBool
-pgresult_m_PQoidValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGresult        *pgr;
-       Oid             oid;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       pgr = JS_GetInstancePrivate(cx, obj, &pgresult_class, NULL);
-       assert(pgr != NULL);
-
-       oid = PQoidValue(pgr);
-
-       if (!JS_NewDoubleValue(cx, (jsdouble)oid, rval)) {
-               QUEUE_EXCEPTION("Internal error!");
-               goto err;
-       }
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
-
-
-
-/*
- * PGcancel object control
- */
-
-static JSObject *
-js_InitPGcancelClass(JSContext *cx, JSObject *obj)
-{
-
-       return (JS_InitClass(cx, obj, NULL, &pgcancel_class,
-           pgcancel_constructor, 0, NULL, pgcancel_methods, NULL, NULL));
-}
-
-/* Non instanciable */
-static JSBool
-pgcancel_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-
-       QUEUE_EXCEPTION("PGcancel class not user-instanciable");
-
-       return JS_FALSE;
-}
-
-static void
-pgcancel_finalize(JSContext *cx, JSObject *obj)
-{
-       PGcancel        *pgc;
-
-       if ((pgc = JS_GetInstancePrivate(cx, obj, &pgcancel_class, NULL))
-           != NULL) {
-               PQfreeCancel(pgc);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-}
-
-
-/*
- * PGcancel object methods
- */
-
-static JSBool
-pgcancel_m_PQfreeCancel(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGcancel        *pgc;
-
-       if (argc != 0) {
-               QUEUE_EXCEPTION("Function allows no arguments");
-               *rval = OBJECT_TO_JSVAL(NULL);
-               return JS_FALSE;
-       }
-
-       if ((pgc = JS_GetInstancePrivate(cx, obj, &pgcancel_class, NULL))
-           != NULL) {
-               PQfreeCancel(pgc);
-               (void) JS_SetPrivate(cx, obj, NULL);
-       }
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_TRUE;
-}
-
-static JSBool
-pgcancel_m_PQcancel(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       PGcancel        *pgc;
-       char            *str;
-       size_t          len;
-       JSString        *s;
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               goto err;
-       }
-       if (!JSVAL_IS_STRING(argv[0])) {
-               QUEUE_EXCEPTION("Argument 1 not a String");
-               goto err;
-       }
-
-       pgc = JS_GetInstancePrivate(cx, obj, &pgcancel_class, NULL);
-       assert(pgc != NULL);
-
-       s = JSVAL_TO_STRING(argv[0]);
-       str = JS_GetStringBytes(s);
-       len = JS_GetStringLength(s);
-
-       *rval = INT_TO_JSVAL(PQcancel(pgc, str, len));
-
-       return JS_TRUE;
-
-err:
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       return JS_FALSE;
-}
diff --git a/tests/js-test/src/classes/js_pgsql.h b/tests/js-test/src/classes/js_pgsql.h
deleted file mode 100644 (file)
index 935b85c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id: js_pgsql.h,v 1.3 2006/07/11 10:25:51 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSPGSQL_H
-#define JSPGSQL_H
-
-#include <jsapi.h>
-
-extern JSObject        *js_InitPGClass(JSContext *, JSObject *);
-
-#endif
diff --git a/tests/js-test/src/classes/js_signal.c b/tests/js-test/src/classes/js_signal.c
deleted file mode 100644 (file)
index c93cc69..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/* $Id: js_signal.c,v 1.3 2005/12/12 18:34:46 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Basic UNIX signal services for ECMAScript
- *
- * XXX
- * I have to see what interface I want to export. There are several
- * possibilities we could use:
- * - Have the shell register signal handlers fore interesting events at
- *   startup and allow scripts to provide a handler function, which if
- *   exists upon reception of a signal, gets executed.  We might then
- *   need to add extra custom checks in the shell for special signals
- *   which if the script doesn't end, might still end the process
- *   i.e. function would be expected to cause the script to exit upon
- *   reception of a SIGTERM signal...
- * - Provide a sigaction-style interface so that the script would be
- *   able to define functions to execute upon reception of certain
- *   signals, or null or such for the signal to be ignored.
- *   This solution might allow better application customization.
- *   If assuming this interface, the following would be exported:
- *   - Signal class, through which static signal properties could be
- *     accessed for signal numbers I.E. Signal.SIGTERM.
- *   - A static method to create/set/unset/ignore a signal/handler
- *     Signal.sigaction()?
- *     It could be provided with the parameters:
- *     Signal.sigaction(FD.SIG*, obj);
- *      Where obj would contain fields sa_handler, sa_mask, sa_flags?
- *     Signal.kill(pid, sig);
- *     Signal.sigaltstack(...) ?
- *     Signal.sigprocmask(...)
- *     Signal.sigsuspend(mask)
- *    And maybe provide the sigsetops(3)?  We possibly could just allow an
- *    array or such instead of sigset_t though if wanted.
- *    I'm not sure I want to provide sigsetjmp()/siglongjmp(). JavaScript has
- *    exceptions anyways.  If allowing sigaltstack(), C would need to allocate
- *    the stacks, so a stack object would need to be exported or such.  I
- *    don't think I want to support this as it's probably not needed by any of
- *    the applications I'll write, I don't want to write a threading library
- *    in JS.
- * - I wonder if it would be safe to invoke a JS function in a signal handler.
- *   If it wasn't, I could simply queue the signal events and then call the
- *   functions for the queue in normal process context.
- *   If doing this, sigaction has to be called to catch any signal the
- *   application wishes, and we would be rolling our own signal handling,
- *   so if wanted we could potentially provide another interface than
- *   sigaction to ECMAScript...
- */
-
-
-
-#include <sys/types.h>
-
-#include <assert.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jsapi.h>
-
-
-
-/* Utility macros */
-#define QUEUE_EXCEPTION(s)     do {                                    \
-       JS_SetPendingException(cx,                                      \
-           STRING_TO_JSVAL(JS_NewStringCopyZ(cx, (s))));               \
-} while (/* CONSTCOND */0)
-
-
-
-/* Prototypes */
-static JSBool  signal_sm_strerror(JSContext *, JSObject *, uintN, jsval *,
-                   jsval *);
-
-
-
-/* Actual class parameters */
-static JSClass signal_class = {
-       "Signal", 0, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
-};
-
-/* Provided static methods */
-static JSFunctionSpec signal_smethods[] = {
-       { "strerror", signal_sm_strerror, 1, 0, 0 },
-       { NULL, NULL, 0, 0, 0 }
-};
-
-/*
- * Provided static properties.
- * We use these to provide ECMAScript with the ability to use system-specific
- * standard C constant macros without us having to tidiously map them
- * individually, or to require other scripts to be used as headers to define
- * them.  Another possibility would have been to supply these parameters as
- * string, but this would have required even slower remapping because of the
- * parsing and string comparisions.
- * We only include those which we consider necessary for now, others may be
- * added easily as needed, provided that they are added in all three maps.
- * I might perhaps develop macros and/or functions to map all these easily
- * from a single map.
- */
-
-struct property_spec {
-       const char      *name;
-       int             value;
-};
-
-#define SP(n) \
-    { #n, n }
-
-static struct property_spec    signal_sprops[] = {
-       SP(SIGHUP),
-       SP(SIGINT),
-       SP(SIGQUIT),
-       SP(SIGILL),
-       SP(SIGTRAP),
-       SP(SIGABRT),
-       SP(SIGEMT),
-       SP(SIGFPE),
-       SP(SIGKILL),
-       SP(SIGBUS),
-       SP(SIGSEGV),
-       SP(SIGSYS),
-       SP(SIGPIPE),
-       SP(SIGALRM),
-       SP(SIGTERM),
-       SP(SIGURG),
-       SP(SIGSTOP),
-       SP(SIGTSTP),
-       SP(SIGCONT),
-       SP(SIGCHLD),
-       SP(SIGTTIN),
-       SP(SIGTTOU),
-       SP(SIGIO),
-       SP(SIGXCPU),
-       SP(SIGXFSZ),
-       SP(SIGVTALRM),
-       SP(SIGPROF),
-       SP(SIGWINCH),
-       SP(SIGINFO),
-       SP(SIGUSR1),
-       SP(SIGUSR2),
-       SP(SIGPWR),
-
-       { NULL, 0 }
-};
-
-#undef SP
-
-
-
-/*
- * Class control functions
- */
-
-JSObject *
-js_InitSignalClass(JSContext *cx, JSObject *obj)
-{
-       JSObject                *proto, *ctor;
-       struct property_spec    *sp;
-
-       if ((proto = JS_InitClass(cx, obj, NULL, &signal_class, NULL,
-           0, NULL, NULL, NULL, signal_smethods)) == NULL) {
-               (void) fprintf(stderr, "Error initializing Signal class\n");
-               return NULL;
-       }
-
-       /* Create static properties */
-       if ((ctor = JS_GetConstructor(cx, proto)) == NULL) {
-               (void) fprintf(stderr, "Signal: JS_GetConstructor == NULL\n");
-               return NULL;
-       }
-       for (sp = signal_sprops; sp->name != NULL; sp++) {
-               if (JS_DefineProperty(cx, ctor, sp->name,
-                   INT_TO_JSVAL(sp->value), NULL, NULL,
-                   JSPROP_READONLY | JSPROP_PERMANENT) == JS_FALSE) {
-                       (void) fprintf(stderr,
-                           "Signal: Error defining property %s\n", sp->name);
-                       return NULL;
-               }
-       }
-
-       return proto;
-}
-
-
-
-/*
- * Static properties functions
- */
-
-
-
-/*
- * Static methods
- */
-
-static JSBool
-signal_sm_strerror(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-    jsval *rval)
-{
-       int             error;
-       JSString        *string;
-
-       *rval = OBJECT_TO_JSVAL(NULL);
-
-       if (argc != 1) {
-               QUEUE_EXCEPTION("Wrong number of arguments");
-               return JS_FALSE;
-       }
-       if (!JSVAL_IS_INT(*argv)) {
-               QUEUE_EXCEPTION("Argument not an integer");
-               return JS_FALSE;
-       }
-       error = (int)JSVAL_TO_INT(*argv);
-
-       if ((string = JS_NewStringCopyZ(cx, "testXXX")) == NULL) {
-               QUEUE_EXCEPTION("Out of memory");
-               return JS_FALSE;
-       }
-
-       *rval = STRING_TO_JSVAL(string);
-
-       return JS_TRUE;
-}
diff --git a/tests/js-test/src/classes/js_signal.h b/tests/js-test/src/classes/js_signal.h
deleted file mode 100644 (file)
index 3690d12..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: js_signal.h,v 1.1 2005/07/19 19:27:28 mmondor Exp $ */
-
-/*
- * Copyright (c) 2005, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#ifndef JSSIGNAL_H
-#define JSSIGNAL_H
-
-extern JSObject        *js_InitSignalClass(JSContext *, JSObject *);
-
-#endif
diff --git a/tests/js-test/src/js-server.c b/tests/js-test/src/js-server.c
deleted file mode 100644 (file)
index f0bfe38..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-/* $Id: js-server.c,v 1.7 2006/07/12 13:47:14 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2005, Matthew Mondor
- */
-
-/*
- * TODO:
- *
- * - Verify with Brendan Eich:
- *   - If reusing the context to execute several other scripts, it is
- *     important that they not be able to add global properties or methods.
- *     This seems to currently work using a custom api_class_property_add().
- *     This however also required standard properties to be shared
- *     (JS_PROP_SHARED), otherwise api_class_property_add() would be called
- *     and even setting values to existing API system properties would fail in
- *     user scripts.  Scealing was also too strict.
- *     I assumed that JS_AddNamedRoot() was required for the API class to
- *     never be freed, so that it can be reused after a call to
- *     js_context_reset().  Perhaps this is not necessary.
- */
-
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include <assert.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <jsapi.h>
-
-#include <js_fd.h>
-#include <js_errno.h>
-#include <js_signal.h>
-#include <js_pgsql.h>
-
-
-
-/*
- * DEFINITIONS
- */
-
-/* Size runtime objects must take to run the GC */
-#define GCBYTES    1048576 /* 1MB */
-
-/* Size of stack to allocate for every context */
-#define STACKBYTES 8192    /* 8KB */
-
-/*
- * Structure used to link a context with custom objects we need to perform
- * some cleanup from before destroying the context.  Ideally managed via
- * mmpool(3) in a real world application for slap management and recycling.
- * We'll have one of these per process in our pool of processes.
- */
-typedef struct {
-       JSRuntime       *rt;
-       JSContext       *ctx;
-       JSObject        *global, *class_fd, *class_errno, *class_signal,
-                       *class_pgsql;
-} js_context_t;
-
-/*
- * To hold loaded file objects (actually mmap(2)ed)
- */
-typedef struct {
-       void            *data;
-       size_t          size;
-} file_t;
-
-/*
- * Defaults for the global class
- */
-static JSClass global_class = {
-       "global", 0, JS_PropertyStub, JS_PropertyStub,
-       JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
-       JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
-};
-
-
-
-/*
- * PROTOTYPES
- */
-
-int                    main(int, char **);
-static JSBool          branch_callback(JSContext *, JSScript *);
-
-static file_t          *file_load(const char *);
-static void            file_free(file_t *);
-
-/* Could be an exported API later on */
-static js_context_t    *js_context_init(size_t, size_t);
-static void            js_context_destroy(js_context_t *);
-/* XXX static void             js_context_reset(js_context_t *);*/
-
-
-
-
-
-int
-main(int argc, char **argv)
-{
-       file_t          *file;
-       js_context_t    *cctx;
-
-       if (argc != 2) {
-               (void) fprintf(stderr, "Usage: test <scriptfile>\n");
-               exit(EXIT_FAILURE);
-       }
-       if ((file = file_load(argv[1])) == NULL) {
-               (void) fprintf(stderr, "Error loading '%s'\n", argv[1]);
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * We always need at least one runtime per process, at least one
-        * context per thread and at least a global object per context
-        * (standard classes, like Date).
-        */
-       if ((cctx = js_context_init(GCBYTES, STACKBYTES)) == NULL) {
-               file_free(file);
-               (void) fprintf(stderr, "js_context_init()\n");
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * This is a very useful and important feature, enable our callback
-        * function which will get called whenever the script branches
-        * backwards, returns from a function or exits. It allows us to
-        * even maintain control in cases where the script loops endlessly.
-        */
-       (void) JS_SetBranchCallback(cctx->ctx, branch_callback);
-
-       /*
-        * Now enable addProperty() protection for all classes using our
-        * custom api_class_property_add() function. This will prevent user
-        * code from adding properties or methods to the API class for
-        * instance.
-        * This however requires that properties use the JSPROP_SHARED flag
-        * since addProperty() method would internally get called to create
-        * shadow copies for the runtime otherwise.
-        */
-       /*
-       api_class_protect = JS_TRUE;
-       */
-
-       /*
-        * Now execute script loaded into our file_t.
-        * We simplify this process by calling JS_EvaluateScript() which
-        * will first tokenize/compile the result, and then interpret/run it.
-        * Moreover, it allows the script to optionally return a value
-        * directly like if it was a function.
-        * Alternatively, we could use JS_CompileFile() or JS_CompileScript()
-        * to pre-tokenize the script, and JS_ExecuteScript() to interpret it.
-        */
-       {
-               jsval           rval, pval;
-               JSString        *str;
-               int             i;
-
-               if (JS_EvaluateScript(cctx->ctx, cctx->global, file->data,
-                   file->size, argv[1], 1, &rval)) {
-                       str = JS_ValueToString(cctx->ctx, rval);
-                       (void) printf("Script result: %s\n",
-                           JS_GetStringBytes(str));
-                       /*
-                        * Attempt to call JS function "callMe" if the script
-                        * created it.
-                        */
-                       for (i = 0; i < 10; i++) {
-                               pval = INT_TO_JSVAL(i);
-                               if (!JS_CallFunctionName(cctx->ctx,
-                                   cctx->global, "callMe", 1, &pval, &rval))
-                                       break;
-                       }
-               } else {
-                       /* XXX how to obtain error and stack backtrace? */
-               }
-       }
-
-       /* Cleanup */
-       file_free(file);
-       js_context_destroy(cctx);
-
-       exit(EXIT_SUCCESS);
-}
-
-/*
- * This function is called during the execution of the script so that we can
- * remain in control of the application. If we only allow the scripts to
- * define functions for callbacks, we can use the first instance if this event
- * to abort the script if wanted, as well. We can then set an alternative
- * callback function and execute the script provided functions at specific
- * events. Of course, it also would be possible to use setitimer(2) to have
- * a SIGALRM signal trigger a function at regular set intervals.
- */
-/* ARGSUSED */
-static JSBool
-branch_callback(JSContext *ctx, JSScript *script)
-{
-       static int      count = 0;
-
-       if (++count > 1000) {
-               count = 0;
-               JS_MaybeGC(ctx);
-       }
-
-       /* Returning JS_FALSE here aborts the script */
-       return JS_TRUE;
-}
-
-
-
-/*
- * Could be an exported API
- */
-
-static js_context_t *
-js_context_init(size_t gc_size, size_t stack_size)
-{
-       js_context_t    *cctx;
-
-       if ((cctx = malloc(sizeof(js_context_t))) == NULL ||
-           (cctx->rt = JS_NewRuntime(gc_size)) == NULL ||
-           (cctx->ctx = JS_NewContext(cctx->rt, stack_size)) == NULL ||
-           (cctx->global = JS_NewObject(cctx->ctx, &global_class, NULL,
-               NULL)) == NULL ||
-           !JS_InitStandardClasses(cctx->ctx, cctx->global) ||
-           (cctx->class_fd = js_InitFDClass(cctx->ctx, cctx->global))
-               == NULL ||
-           (cctx->class_errno = js_InitErrnoClass(cctx->ctx, cctx->global))
-               == NULL ||
-           (cctx->class_signal = js_InitSignalClass(cctx->ctx, cctx->global))
-               == NULL ||
-           (cctx->class_pgsql = js_InitPGClass(cctx->ctx, cctx->global))
-               == NULL) {
-               /* An error, free any partially allocated resources */
-               if (cctx != NULL)
-                       js_context_destroy(cctx);
-
-               return NULL;
-       }
-
-       return cctx;
-}
-
-static void
-js_context_destroy(js_context_t *cctx)
-{
-
-       assert(cctx != NULL);
-
-       if (cctx->ctx != NULL)
-               JS_DestroyContext(cctx->ctx);
-       if (cctx->rt != NULL)
-               JS_DestroyRuntime(cctx->rt);
-
-       free(cctx);
-}
-
-/*
- * This function should permit to restore the context to a consistent, known
- * state before a new script can be executed using the same context instead of
- * having to destroy and recreate contexts everytime.
- */
-/* ARGSUSED */
-/* XXX
-static void
-js_context_reset(js_context_t *cctx)
-{
-
-}
-*/
-
-
-/*
- * Loads specified file and returns a file_t pointer.  Note that we only
- * internally keep the memory map for read access to the file, rather than an
- * open filedescriptor.
- */
-static file_t *
-file_load(const char *filename)
-{
-       int             fd;
-       struct stat     st;
-       file_t          *file;
-
-       assert(filename != NULL);
-
-       if ((fd = open(filename, O_RDONLY)) != -1) {
-               if (fstat(fd, &st) == 0) {
-                       if ((file = malloc(sizeof(file_t))) != NULL) {
-                               file->size = (size_t)st.st_size;
-
-                               if ((file->data = mmap(NULL, file->size,
-                                   PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0))
-                                   != MAP_FAILED) {
-                                       (void) close(fd);
-                                       return file;
-                               }
-
-                               free(file);
-                       }
-               }
-               (void) close(fd);
-       }
-
-       return NULL;
-}
-
-/*
- * Frees a file_t which was returned by a previous file_load() call.
- */
-static void
-file_free(file_t *file)
-{
-
-       assert(file != NULL);
-
-       (void) munmap(file->data, file->size);
-       free(file);
-}
diff --git a/tests/js-test/util/spidermonkey-config b/tests/js-test/util/spidermonkey-config
deleted file mode 100755 (executable)
index 6a3cc76..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/sh
-#
-# Configure script to help build scripts
-# by Matthew Mondor
-
-CFLAGS='-I/usr/local/spidermonkey/include -DXP_UNIX'
-LDFLAGS='-Wl,-R/usr/local/spidermonkey/lib -L/usr/local/spidermonkey/lib -ljs'
-
-DLDFLAGS='-Wl,-R/usr/local/spidermonkey/lib -L/usr/local/spidermonkey/lib -ljs_dbg'
-
-VERSION='SpiderMonkey 1.5-rc6A'
-
-usage()
-{
-       echo
-       echo 'Usage: spidermonkey-config [-v] [-c] [-l] [-d]'
-       echo
-       echo ' -v : Shows SpiderMonkey version'
-       echo ' -c : Shows flags suitable to append to $CFLAGS'
-       echo ' -l : Shows flags suitable to append to $LDFLAGS'
-       echo ' -d : Shows debugging versions of the flags'
-       echo
-}
-
-if [ -z $@ ]; then
-       usage
-       exit 0
-fi
-
-while getopts dclv c; do
-       case $c in
-       d)
-               LDFLAGS="$DLDFLAGS"
-               ;;
-       c)
-               echo $CFLAGS
-               ;;
-       l)
-               echo $LDFLAGS
-               ;;
-       v)
-               echo $VERSION
-               ;;
-       *)
-               usage
-               exit 0
-               ;;
-       esac
-done
diff --git a/tests/kqueue/GNUmakefile b/tests/kqueue/GNUmakefile
deleted file mode 100644 (file)
index 4ae0616..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# $Id: GNUmakefile,v 1.7 2006/04/23 04:40:14 mmondor Exp $
-
-MMLIB_PATH := ../../mmlib
-
-MMLIBS := $(addprefix ${MMLIB_PATH}/,mmpool.o mmstring.o mmarch.o)
-LIBS := -lc
-OBJS := main.o net.o kqueue.o sendq.o recvq.o packets.o daemon.o client.o
-CFLAGS += -Wall
-BINS := daemon
-
-all: $(BINS)
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I${MMLIB_PATH} -o $@ $<
-
-
-daemon: $(MMLIBS) $(LIBS) $(OBJS)
-       cc -o $@ $(MMLIBS) $(OBJS) $(LIBS)
-
-
-clean:
-       rm -f $(BINS) $(OBJS) $(MMLIBS) $(LIBS)
diff --git a/tests/kqueue/README b/tests/kqueue/README
deleted file mode 100644 (file)
index 3d58fc4..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-$Id: README,v 1.3 2006/04/23 04:40:14 mmondor Exp $
-
-If this all works fine, it might be the basis of a multiplayer
-networking game.  However, this is primarily a test to learn kqueue
-and observe its efficiency, as well as to experiment using TCP for
-such massive multiplayer games on today's networks and internet.
-
-Many games that used TCP for LAN use a while back had to develop
-UDP based protocols to be efficient enough for dialup users or
-other internet users.  We will determine if this is still necessary
-on today's average internet latencies.
-
-We probably still want to prioritize some packets over others.
-For instance, we might drop outgoing position update packets which
-cannot be sent immediately instead of queueing them, allowing less
-frequent updates to slow connections while not needing to provide
-multiple independent game heart rates.
-
-We do not expect to have to port the server part of the game, wich
-is intended to run on BSD systems supporting the kqueue(2) system
-only.  We could have used an event library, however we wanted to
-avoid including non-BSD licensed components.  Although there is a
-BSD licensed libevent as part of NetBSD, using kqueue directly
-allows a few fancy optimization tricks which would require a new
-portable events library to be designed to allow to achieve the full
-advantages of kqueue using an abstracted library.
-
-The client code, however, will be portable and should be able to
-run on Win32 without needing the cygwin runtime libraries.  The
-SDL dependency is reasonable, and can be provided separately, so
-mingw will be used to create those executables.  The client will
-however primarily be developped on NetBSD.  Like SDL, OpenGL
-libraries shouldn't be a problem either.
-
-To avoid using cygwin, and because Win32 winsock does not conform
-to BSD sockets API standards, we expect to have to write a simple
-portable networking layer for use in the client.
-
-
-TODO
-
-- At this point to advance further a client needs to be written.
-- We probably don't need to align packets, we only need to make sure
-  that their size is 32-bit aligned, and that their 16-bit fields are
-  16-bit aligned, their 32-bit ones 32-bit aligned.  Packet type field
-  can be 8-bit.  If we allowed arbitrary offsets when buffering packets,
-  we would need to copy each packet to an aligned buffer as we process them.
-  Evaluate which is more advantageous.
diff --git a/tests/kqueue/client.c b/tests/kqueue/client.c
deleted file mode 100644 (file)
index 7fa0caa..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/* $Id: client.c,v 1.9 2006/04/23 04:40:14 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include "client.h"
-#include "kqueue.h"
-#include "conf.h"
-
-
-
-list_t                 clients_list;
-static list_t          clients_gc_list;
-static pool_t          clients_pool;
-
-
-
-void
-client_init(void)
-{
-       DLIST_INIT(&clients_list);
-       DLIST_INIT(&clients_gc_list);
-
-       if (!pool_init(&clients_pool, "clients_pool", malloc, free, NULL,
-           NULL, sizeof(client_t), MAX_CLIENTS + 1, 1, 1)) {
-               syslog(LOG_NOTICE, "pool_init() - %s", strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-
-}
-
-/*
- * Enables the write polling filter for the specified client.
- */
-void
-client_enable_write_polling(void *args)
-{
-       client_t        *c = (client_t *)args;
-
-       if (c->writepolling)
-               return;
-
-       kqueue_sev_alloc(1);
-       kqueue_sev_add(c->fd, EVFILT_WRITE, EV_ENABLE, 0, 0, (intptr_t)c);
-
-       c->writepolling = 1;
-}
-
-inline int
-client_write(client_t *c, uint8_t *buf, size_t size, int buffer)
-{
-
-       if (sendq_write(&c->sendq, buf, size, client_enable_write_polling, c,
-           buffer) == -1) {
-               syslog(LOG_NOTICE, "sendq_write(%u) - %s", size,
-                   strerror(errno));
-               return -1;
-       }
-
-       return 0;
-}
-
-/*
- * XXX We should do connection rate/concurrency checking on address here.
- */
-client_t *
-client_create(int fd, struct sockaddr *saddr)
-{
-       client_t        *c;
-
-       if (DLIST_NODES(&clients_list) > MAX_CLIENTS) {
-               syslog(LOG_NOTICE, "client_create() - MAX_CLIENTS reached");
-               return NULL;
-       }
-
-       if ((c = (client_t *)pool_alloc(&clients_pool, FALSE)) != NULL) {
-               if (sendq_init(&c->sendq, fd, SENDQ_SIZE) != -1) {
-                       if (recvq_init(&c->recvq, fd, RECVQ_SIZE) != -1) {
-                               c->fd = fd;
-                               (void) memcpy(&c->saddr, saddr,
-                                   sizeof(struct sockaddr));
-
-                               c->object.x = random() % WORLD_X_MAX;
-                               c->object.y = random() % WORLD_Y_MAX;
-                               c->object.direction = c->object.i_direction =
-                                  random() % 1000;
-                               c->object.thrust = c->object.i_thrust =
-                                  random() % 20;
-
-                               c->authenticated = c->todestroy =
-                                   c->toclose = 0;
-                               c->writepolling = 1;
-                               c->askedping = 0;
-
-                               DLIST_APPEND(&clients_list, &c->node);
-
-                               return c;
-                       }
-                       syslog(LOG_NOTICE,
-                           "client_create() - recvq_init() - %s",
-                           strerror(errno));
-                       sendq_destroy(&c->sendq);
-               }
-               syslog(LOG_NOTICE,
-                   "client_create() - sendq_init() - %s", strerror(errno));
-               pool_free((pnode_t *)c);
-       }
-       syslog(LOG_NOTICE, "client_create() - pool_alloc() - %s",
-           strerror(errno));
-
-       return NULL;
-}
-
-void
-client_destroy_mark(client_t *c)
-{
-
-       if (c->todestroy)
-               return;
-
-       c->todestroy = 1;
-       DLIST_SWAP(&clients_gc_list, &clients_list, &c->node, FALSE);
-}
-
-void
-client_destroy_marked(void)
-{
-       node_t          *i, *n;
-       client_t        *c;
-
-       for (i = DLIST_TOP(&clients_gc_list); i != NULL; i = n) {
-               n = DLIST_NEXT(i);
-
-               c = (client_t *)i;
-               /* Closing descriptor automatically deletes its kevents */
-               (void) close(c->fd);
-               recvq_destroy(&c->recvq);
-               sendq_destroy(&c->sendq);
-               pool_free((pnode_t *)c);
-       }
-       DLIST_INIT(&clients_gc_list);
-}
diff --git a/tests/kqueue/client.h b/tests/kqueue/client.h
deleted file mode 100644 (file)
index a9575fc..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* $Id: client.h,v 1.7 2006/04/03 08:56:45 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#ifndef _CLIENT_H_
-#define _CLIENT_H_
-
-
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <mmpool.h>
-#include <mmlist.h>
-
-#include "sendq.h"
-#include "recvq.h"
-
-
-
-typedef struct object {
-       node_t          region;
-       int32_t         direction, thrust;
-       int32_t         i_direction, i_thrust;
-       int32_t         x, y;
-} object_t;
-
-typedef struct client {
-       node_t          node;
-       object_t        object;
-       sendq_t         sendq;
-       recvq_t         recvq;
-       int             fd;
-       struct sockaddr saddr;
-       int             authenticated, todestroy, toclose, writepolling,
-                       askedping;
-} client_t;
-
-
-
-extern list_t  clients_list;
-
-
-void           client_init(void);
-void           client_enable_write_polling(void *);
-inline int     client_write(client_t *, u_int8_t *, size_t, int);
-
-client_t       *client_create(int, struct sockaddr *);
-void           client_destroy_mark(client_t *);
-void           client_destroy_marked(void);
-
-
-
-#endif
diff --git a/tests/kqueue/conf.h b/tests/kqueue/conf.h
deleted file mode 100644 (file)
index 5720c1a..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* $Id: conf.h,v 1.9 2006/04/23 04:40:14 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#ifndef _CONF_H_
-#define _CONF_H_
-
-
-
-#define SERVER_VERSION 1
-#define SERVER_STRING  "daemon/mmondor\n"
-
-#define FPS            10
-#define FPS_MS         (1000 / FPS)
-
-#define WORLD_X_MAX    640
-#define WORLD_Y_MAX    480
-
-#define MAX_CLIENTS    128
-#define R_EVENTS       (MAX_CLIENTS * 2)
-#define S_EVENTS       (MAX_CLIENTS * 2)
-
-#define SENDQ_SIZE     16384
-#define RECVQ_SIZE     1024
-
-/* In seconds */
-#define INPUT_TIMEOUT  30
-#define PING_TIMEOUT   5
-
-#define PIDFILE                "/tmp/daemon.pid"
-
-
-
-#endif
diff --git a/tests/kqueue/daemon.c b/tests/kqueue/daemon.c
deleted file mode 100644 (file)
index bd38e65..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/* $Id: daemon.c,v 1.3 2006/04/23 04:40:14 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Procedure for becoming an detached daemon, as well as to prepare process
- * signal handling.  Since we'll be catching signal events through kqueue(2),
- * We simply ignore all signals for which we don't want the default behavior.
- */
-
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <mmstring.h>
-
-#include <conf.h>
-
-
-
-static int     signal_init(void);
-static void    pidfile_write(const char *);
-
-
-
-static int
-signal_init(void)
-{
-       struct sigaction        act;
-       int                     i;
-       int                     sigs[] = {
-               SIGHUP,
-               SIGINT,
-               SIGPIPE,
-               SIGALRM,
-               SIGTERM,
-               SIGTTIN,
-               SIGTTOU,
-               SIGIO,
-               SIGXCPU,
-               SIGXFSZ,
-               SIGVTALRM,
-               SIGPROF,
-               SIGUSR1,
-               SIGUSR2
-       };
-
-       act.sa_handler = SIG_IGN;
-       act.sa_flags = SA_NOCLDSTOP;
-       (void) sigemptyset(&act.sa_mask);
-
-       for (i = 0; i < (sizeof(sigs) / sizeof(int)); i++) {
-               if (sigaction(sigs[i], &act, NULL) != 0) {
-                       syslog(LOG_NOTICE,
-                           "signal_init() - sigaction(%d) - %s",
-                           sigs[i], strerror(errno));
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Writes our process ID number to specified file.  To be called before
- * chroot(2) or dropping privileges.
- */
-static void
-pidfile_write(const char *file)
-{       
-       char    str[16];
-       int     fd;
-
-       if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600)) != -1) {
-               (void) snprintf(str, 15, "%d\n", getpid());
-               (void) write(fd, str, mm_strlen(str));
-               (void) close(fd);
-       } else  
-               syslog(LOG_NOTICE, "pidfile_write() - open(%s) - %s",
-                   file, strerror(errno));
-}
-
-int
-daemon_init(void)
-{
-       pid_t   pid;
-       int     fd;
-
-       /* Create new process */
-       if ((pid = fork()) == -1) {
-               syslog(LOG_NOTICE, "fork() - %s", strerror(errno));
-               return -1;
-       }
-       if (pid != 0)
-               exit(EXIT_SUCCESS);
-
-       pidfile_write(PIDFILE);
-
-       /* Create new process group and detach */
-       (void) setsid();
-       (void) chdir("/");
-       if ((fd = open("/dev/null", O_RDWR)) != -1) {
-               (void) dup2(fd, STDIN_FILENO);
-               (void) dup2(fd, STDOUT_FILENO);
-               (void) dup2(fd, STDERR_FILENO);
-               if (fd > STDERR_FILENO)
-                       (void) close(fd);
-       } else
-               syslog(LOG_NOTICE, "daemon_init() - open(/dev/null) - %s",
-                   strerror(errno));
-
-       if (signal_init() != 0)
-               return -1;
-
-       return 0;
-}
diff --git a/tests/kqueue/daemon.h b/tests/kqueue/daemon.h
deleted file mode 100644 (file)
index 32ec407..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* $Id: daemon.h,v 1.2 2006/03/31 20:57:08 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#ifndef _DAEMON_H_
-#define _DAEMON_H_
-
-
-
-int    daemon_init(void);
-
-
-
-#endif
diff --git a/tests/kqueue/kqueue.c b/tests/kqueue/kqueue.c
deleted file mode 100644 (file)
index a5a8628..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-/* $Id: kqueue.c,v 1.11 2006/04/03 21:06:08 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <errno.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <mmarch.h>
-
-#include "kqueue.h"
-#include "client.h"
-#include "packets.h"
-#include "net.h"
-#include "conf.h"
-
-
-
-static struct kevent   rev[R_EVENTS], sev[S_EVENTS];
-static int             kqid, rev_cnt, sev_cnt;
-
-
-
-/* The following functions simply exit on failure, because they are critical */
-
-void
-kqueue_init(void)
-{
-
-       if ((kqid = kqueue()) == -1) {
-               syslog(LOG_NOTICE, "kqueue_init() - kqueue() - %s",
-                   strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-
-       sev_cnt = 0;
-}
-
-void
-kqueue_addlisten(int fd)
-{
-
-       EV_SET(sev, fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, (intptr_t)NULL);
-       if (kevent(kqid, sev, 1, NULL, 0, NULL) == -1) {
-               syslog(LOG_NOTICE, "kqueue_addlisten() - kevent(%d) - %s",
-                   fd, strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-
-}
-
-void
-kqueue_addsignal(int sig)
-{
-
-       EV_SET(sev, sig, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0,
-           (intptr_t)NULL);
-       if (kevent(kqid, sev, 1, NULL, 0, NULL) == -1) {
-               syslog(LOG_NOTICE, "kqueue_addsignal() - kevent(%d) - %s",
-                   sig, strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-}
-
-void
-kqueue_addtimer0(int64_t ms)
-{
-
-       EV_SET(sev, 0, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, ms,
-           (intptr_t)NULL); 
-       if (kevent(kqid, sev, 1, NULL, 0, NULL) == -1) {
-               syslog(LOG_NOTICE, "kevent_addtimer0() - kevent(%lld) - %s",
-                   ms, strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-}
-
-void
-kqueue_main(void)
-{
-
-       for (;;) {
-               int             e, i;
-               struct kevent   *kev;
-               client_t        *c;
-
-               /*
-                * Fusion to only require one kevent(2) call if there are
-                * events to send.  Wait for events to occur.
-                * This also allows us to catch error events.
-                */
-               if ((rev_cnt = kevent(kqid, sev, sev_cnt, rev, R_EVENTS, NULL))
-                   == -1) {
-                       syslog(LOG_NOTICE, "kevent(1) - %s", strerror(errno));
-                       continue;
-               }
-               sev_cnt = 0;
-
-               /* Run through received events and process them */
-               for (e = 0; e < rev_cnt; e++) {
-                       kev = &rev[e];
-
-                       /* Report errors if any */
-                       if ((kev->flags & EV_ERROR) != 0) {
-                               syslog(LOG_NOTICE,
-                                   "EV_ERROR: ident=%d filter=%d flags=%d "
-                                   "fflags=%d data=%lld udata=%p",
-                                   kev->ident, kev->filter, kev->flags,
-                                   kev->fflags, kev->data,
-                                   (void *)kev->udata);
-                               continue;
-                       }
-
-                       /* Process signals if any */
-                       if (kev->filter == EVFILT_SIGNAL) {
-                               switch (kev->ident) {
-                               case SIGTERM:
-                                       syslog(LOG_NOTICE,
-                                           "Received SIGTERM, exiting");
-                                       exit(EXIT_SUCCESS);
-                                       break;
-                               }
-                               continue;
-                       }
-
-                       /* Process timeouts if any */
-                       if (kev->filter == EVFILT_TIMER) {
-                               if (kev->ident == 0) {
-                                       /* Main heartrate timer */
-                                       update();
-                                       continue;
-                               }
-                               /*
-                                * XXX input timeout timers?
-                                * We'll need an input timer per socket,
-                                * which gets canceled whenever input arrives,
-                                * but once expires launches a server ping
-                                * request which then should trigger another
-                                * timer, which if pong occurs gets restarted,
-                                * but if it exceeds client gets dropped.
-                                * We'll also need to match timer events with
-                                * filedescriptors, as well as reason for
-                                * timeout...  And we'll need to make sure to
-                                * clean out any pending timers when marking a
-                                * client to be destroyed (or when destroying
-                                * them, at least).
-                                */
-                       }
-
-                       if (kev->ident == listen_fd) {
-                               int     t;
-
-                               /*
-                                * Accept new connections, create clients and
-                                * add new descriptors to the kqueue set,
-                                * buffering them to minimize syscalls.
-                                */
-                               for (i = 0, t = kev->data; i < t; i++) {
-                                       struct sockaddr saddr;
-                                       socklen_t       saddrl;
-                                       client_t        *c;
-                                       int             fd;
-
-                                       saddrl = sizeof(struct sockaddr);
-                                       if ((fd = accept(listen_fd, &saddr,
-                                           &saddrl)) == -1)
-                                               continue;
-
-                                       if ((c = client_create(fd, &saddr))
-                                           == NULL) {
-                                               (void) close(fd);
-                                               continue;
-                                       }
-
-                                       kqueue_sev_alloc(2);
-                                       kqueue_sev_add(fd, EVFILT_READ,
-                                           EV_ADD | EV_EOF | EV_ENABLE, 0, 0,
-                                           (intptr_t)c);
-                                       kqueue_sev_add(fd, EVFILT_WRITE,
-                                           EV_ADD | EV_EOF | EV_ENABLE, 0, 0,
-                                           (intptr_t)c);
-
-                                       /* Send auth request packet */
-                                       if (spacket_auth_send(c) == -1) {
-                                               client_destroy_mark(c);
-                                               continue;
-                                       }
-                               }
-                               continue;
-                       }
-
-                       /*
-                        * Don't process any more events for marked to be
-                        * destroyed clients, or those without an associated
-                        * udata.  When client descriptor must be closed and
-                        * client structure freed, we make sure to first mark
-                        * it as to destroy within this loop, since it's
-                        * possible for more than one event to occur for a
-                        * single descriptor.  We use client_destroy_mark()
-                        * for this purpose.
-                        */
-                       if ((c = (client_t *)kev->udata) == NULL) {
-                               /* XXX */
-                               syslog(LOG_NOTICE, "udata == NULL");
-                               continue;
-                       }
-                       if (c->todestroy)
-                               continue;
-
-                       if ((kev->flags & EV_EOF) != 0) {
-                               client_destroy_mark(c);
-                               continue;
-                       }
-
-                       if (kev->filter == EVFILT_WRITE) {
-                               int     f;
-
-                               /*
-                                * If there's a sendq for the client,
-                                * attempt to flush it.  If there's an error,
-                                * drop client.
-                                * If client was marked to be closed, and we
-                                * finished flusing data, also mark it to be
-                                * destroyed, since were done with it.
-                                */
-                               if ((f = sendq_flush(&c->sendq, kev->data))
-                                   == -1 || (f == 0 && c->toclose))
-                                       client_destroy_mark(c);
-                               else if (f == 0) {
-                                       /*
-                                        * No more data to send, we can thus
-                                        * temporarily disable write events
-                                        * for this descriptor.  client_write()
-                                        * will re-enable it as necessary.
-                                        */
-                                       kqueue_sev_alloc(1);
-                                       kqueue_sev_add(c->fd, EVFILT_WRITE,
-                                           EV_DISABLE, 0, 0, (intptr_t)c);
-                                       c->writepolling = 0;
-                               }
-                               continue;
-                       }
-
-                       if (kev->filter == EVFILT_READ) {
-                               int16_t         *buf;
-                               size_t          size;
-
-                               /*
-                                * Data to read from client.  Simply read it
-                                * into a queue to process it at the next
-                                * server heartbeat event.
-                                * XXX We should be able to process ping
-                                * requests immediately.  This means that
-                                * we need recvq_read() to report more
-                                * information.
-                                */
-                               if (recvq_read(&c->recvq, &buf, &size) == -1) {
-                                       client_destroy_mark(c);
-                                       continue;
-                               }
-
-                               /* Convert packet_type to host endian */
-                               *buf = BYTEORDER_HOST16(*buf);
-
-                               /*
-                                * If ping packet, process immediately
-                                * and discard packet from recvq.
-                                * We only allow ping if c->askedping
-                                * is unset, and we set it.  It will be unset
-                                * at the next server heart beat.  This way,
-                                * we only allow clients to ping once per
-                                * frame at most.
-                                */
-                               if (*buf == CPACKET_PING &&
-                                   size == sizeof(struct cpacket_ping)) {
-                                       if (!c->authenticated ||
-                                           c->askedping ||
-                                           spacket_pong_send(c) == -1) {
-                                               client_destroy_mark(c);
-                                               continue;
-                                       }
-                                       recvq_rewind(&c->recvq, size);
-                               }
-
-                               continue;
-                       }
-
-               }
-               /* Destroy marked to be destroyed clients */
-               client_destroy_marked();
-       }
-       /* NOTREACHED */
-}
-
-
-/* Utility functions */
-
-inline void
-kqueue_sev_alloc(int n)
-{
-
-       if (sev_cnt > S_EVENTS - n) {
-               if (kevent(kqid, sev, sev_cnt, NULL, 0, NULL) == -1)
-                       syslog(LOG_NOTICE,
-                           "kqueue_sev_alloc() - kevent() - %s",
-                           strerror(errno));
-               sev_cnt = 0;
-       }
-}
-
-inline void
-kqueue_sev_add(uintptr_t ident, uint32_t filter, uint32_t flags,
-    uint32_t fflags, int64_t data, intptr_t udata)
-{
-
-       /*
-        * Be careful to avoid macro side effects, do not use &sev[sev_cnt++]
-        */
-       EV_SET(&sev[sev_cnt], ident, filter, flags, fflags, data, udata);
-       sev_cnt++;
-}
diff --git a/tests/kqueue/kqueue.h b/tests/kqueue/kqueue.h
deleted file mode 100644 (file)
index 700e063..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* $Id: kqueue.h,v 1.4 2006/04/01 00:46:24 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#ifndef _KQUEUE_H_
-#define _KQUEUE_H_
-
-
-
-#include <sys/event.h>
-#include <sys/time.h>
-
-
-
-void           kqueue_init(void);
-void           kqueue_addlisten(int);
-void           kqueue_addsignal(int);
-void           kqueue_addtimer0(int64_t);
-void           kqueue_main(void);
-inline void    kqueue_sev_alloc(int);
-inline void    kqueue_sev_add(uintptr_t, uint32_t, uint32_t, uint32_t,
-                   int64_t, intptr_t);
-
-
-
-#endif
diff --git a/tests/kqueue/main.c b/tests/kqueue/main.c
deleted file mode 100644 (file)
index 24611a0..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* $Id: main.c,v 1.10 2006/04/01 00:46:24 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <sys/types.h>
-#include <sys/event.h>
-#include <sys/socket.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <mmpool.h>
-#include <mmlist.h>
-
-#include "daemon.h"
-#include "net.h"
-#include "sendq.h"
-#include "packets.h"
-#include "client.h"
-#include "conf.h"
-#include "kqueue.h"
-
-
-
-int                    main(int, char **);
-
-
-
-int
-main(int argc, char **argv)
-{
-
-       (void) openlog("daemon", LOG_NDELAY | LOG_PID, LOG_USER);
-
-       if (daemon_init() != 0)
-               exit(EXIT_FAILURE);
-       syslog(LOG_NOTICE, "Started");
-
-       /*
-        * The following funtions exit whenever there's a problem, because
-        * they set up critical things.
-        */
-       client_init();
-       kqueue_init();
-       net_init();
-       kqueue_addlisten(listen_fd);
-       kqueue_addsignal(SIGTERM);
-       kqueue_addtimer0(FPS_MS);
-
-       kqueue_main();
-       /* NOTREACHED */
-
-       return EXIT_SUCCESS;
-}
diff --git a/tests/kqueue/net.c b/tests/kqueue/net.c
deleted file mode 100644 (file)
index 6202c98..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/* $Id: net.c,v 1.2 2006/04/01 00:46:24 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <sys/types.h>
-#include <syslog.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <netdb.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <mmstring.h>
-
-#include "net.h"
-#include "conf.h"
-
-
-
-static int     net_listen(const char *, int, int);
-
-
-
-int    listen_fd;
-
-
-
-void
-net_init(void)
-{
-
-       if ((listen_fd = net_listen("0.0.0.0", 7777, MAX_CLIENTS)) == -1) {
-               syslog(LOG_NOTICE, "net_listen() - %s", strerror(errno));
-               exit(EXIT_FAILURE);
-       }
-}
-
-static int
-net_listen(const char *addr, int port, int backlog)
-{
-       int                     fd, opt;
-       struct linger           linger;
-       struct protoent         *pent;
-       struct sockaddr_in      server;
-
-       fd = -1;
-
-       mm_memclr(&server, sizeof(struct sockaddr_in));
-       server.sin_family = AF_INET;
-       if (inet_pton(AF_INET, addr, &server.sin_addr) != 1) {
-               syslog(LOG_NOTICE, "inet_pton(%s) - %s", addr,
-                   strerror(errno));
-               goto err;
-       }
-       server.sin_port = htons((short)port);
-
-       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
-               syslog(LOG_NOTICE, "socket() - %s", strerror(errno));
-               goto err;
-       }
-
-       opt = 1;
-       if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)))
-           == -1)
-               syslog(LOG_NOTICE, "setsockopt(SO_REUSEADDR) - %s",
-                   strerror(errno));
-       if ((setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(int)))
-           == -1)
-               syslog(LOG_NOTICE, "setsockopt(SO_KEEPALIVE) - %s",
-                   strerror(errno));
-
-       linger.l_onoff = 0;
-       linger.l_linger = 0;
-       if ((setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger,
-           sizeof(struct linger))) == -1)
-               syslog(LOG_NOTICE, "setsockopt(SO_LINGER) - %s",
-                   strerror(errno));
-
-       /* XXX Set buffer sizes? */
-
-       if ((pent = getprotobyname("TCP")) != NULL) {
-               opt = 1;
-               if ((setsockopt(fd, pent->p_proto, TCP_NODELAY, &opt,
-                   sizeof(int))) == -1)
-                       syslog(LOG_NOTICE, "setsockopt(TCP_NODELAY) - %s",
-                           strerror(errno));
-       } else
-               syslog(LOG_NOTICE, "getprotobyname(TCP) - %s",
-                   strerror(errno));
-
-       if ((opt = fcntl(fd, F_GETFL, NULL)) != -1) {
-               if (fcntl(fd, F_SETFL, opt | O_NONBLOCK) == -1) {
-                       syslog(LOG_NOTICE, "fcntl(F_SETFL) - %s",
-                           strerror(errno));
-                       goto err;
-               }
-       } else
-               syslog(LOG_NOTICE, "fcntl(F_GETFL) - %s", strerror(errno));
-
-       if ((bind(fd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)))
-           != 0) {
-               syslog(LOG_NOTICE, "bind(%s:%d) - %s", addr, port,
-                   strerror(errno));
-               goto err;
-       }
-
-       if (listen(fd, backlog) == -1) {
-               syslog(LOG_NOTICE, "listen(%s:%d) - %s", addr, port,
-                   strerror(errno));
-               goto err;
-       }
-
-       return fd;
-
-err:
-       if (fd != -1)
-               (void) close(fd);
-
-       return -1;
-}
diff --git a/tests/kqueue/net.h b/tests/kqueue/net.h
deleted file mode 100644 (file)
index 3607cc9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: net.h,v 1.2 2006/04/01 00:46:24 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#ifndef _NET_H_
-#define _NET_H_
-
-
-
-void           net_init(void);
-
-
-
-extern int     listen_fd;
-
-
-
-#endif
diff --git a/tests/kqueue/packets.c b/tests/kqueue/packets.c
deleted file mode 100644 (file)
index 83da958..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/* $Id: packets.c,v 1.14 2006/04/03 20:38:43 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * To validate a received packet, we'll make sure that it's larger than
- * sizeof(int), and that the first integer consists of a valid expected packet
- * type ID within range.  If so, we verify if packet length really corresponds
- * to the packet type, and then can interpret the packet information.
- * An actual network packet may contain a number of these packets.
- * We thus must be able to efficiently determine each packet's length.
- * Since we're using TCP, it should be enough.  However, on the server side
- * especially, proper sanity checking on input must be done to avoid crashing
- * the server because of unexpected data processing.
- */
-
-
-
-#include <stdlib.h>
-
-#include <mmstring.h>
-#include <mmarch.h>
-
-#include "packets.h"
-#include "client.h"
-#include "sendq.h"
-#include "conf.h"
-
-
-
-static int     cpacket_auth_handler(client_t *, uint16_t *);
-static int     cpacket_ping_handler(client_t *, uint16_t *);
-static int     cpacket_pong_handler(client_t *, uint16_t *);
-static int     cpacket_direction_handler(client_t *, uint16_t *);
-static int     cpacket_thrust_handler(client_t *, uint16_t *);
-static int     cpacket_torp_handler(client_t *, uint16_t *);
-static int     cpacket_quit_handler(client_t *, uint16_t *);
-
-
-
-static struct packet_index     cpacket_index[CPACKET_MAX] = {
-       {sizeof(struct cpacket_auth), cpacket_auth_handler},
-       {sizeof(struct cpacket_ping), cpacket_ping_handler},
-       {sizeof(struct cpacket_pong), cpacket_pong_handler},
-       {sizeof(struct cpacket_direction), cpacket_direction_handler},
-       {sizeof(struct cpacket_thrust), cpacket_thrust_handler},
-       {sizeof(struct cpacket_torp), cpacket_torp_handler},
-       {sizeof(struct cpacket_quit), cpacket_quit_handler}
-};
-
-
-
-void
-update(void)
-{
-       node_t          *nod, *next;
-       client_t        *c;
-       uint8_t         *data;
-       size_t          size, off;
-
-       for (nod = DLIST_TOP(&clients_list); nod != NULL; nod = next) {
-               next = DLIST_NEXT(nod);
-               c = (client_t *)nod;
-
-               if (c->todestroy || c->toclose)
-                       continue;
-
-               /* Reset ping request throttling flag */
-               c->askedping = 0;
-
-               /* First process incomming packets */
-               recvq_content(&c->recvq, &data, &size);
-               for (off = 0; off < size; ) {
-                       int16_t *id;
-
-                       /*
-                        * Verify packet type ID. It already has been
-                        * converted to host endian byte order, unlike other
-                        * packet fields.
-                        */
-                       id = (int16_t *)&data[off];
-                       *id = BYTEORDER_HOST16(*id);
-                       if (*id < 0 || *id > CPACKET_MAX) {
-                               client_destroy_mark(c);
-                               break;
-                       }
-
-                       /* There must be enough data for packet size */
-                       if (size - off < cpacket_index[*id].size) {
-                               /*
-                                * Kill authentucated client if other packets
-                                * than CPACKET_AUTH
-                                */
-                               if (!c->authenticated && *id != CPACKET_AUTH)
-                                       goto k;
-
-                               /*
-                                * XXX We'll need to also do special
-                                * processing for chat packets, since they'll
-                                * have arbitrary length.  They'll still need
-                                * to be 16-bit aligned, too.
-                                */
-
-                               /* Kill client on packet processing error */
-                               if (cpacket_index[*id].handler(c,
-                                   (uint16_t *)off) == -1)
-                                       goto k;
-                       } else
-                               goto k;
-
-                       /* Process next packet if any */
-                       off += cpacket_index[*id].size;
-                       continue;
-
-k:
-                       client_destroy_mark(c);
-                       break;
-               }
-
-               /*
-                * XXX I don't like having to run the clients list all over,
-                * to then run through all objects (including clients) to
-                * update them, and then yet again through all objects to send
-                * updates to all clients.
-                */
-
-               /* Run game frame on all objects */
-               DLIST_FOREACH(&clients_list, nod) {
-                       client_t        *c = (client_t *)nod;
-
-                       /*
-                       if (!c->authenticated)
-                               continue;
-                        */
-
-                       /*
-                        * First update direction and thrust.
-                        * XXX I could do a small function or macro to deal
-                        * with similar situations, i.e.
-                        * change_update(int goal, int *current, int steps);
-                        */
-                       if (c->object.direction < c->object.i_direction)
-                               c->object.direction++;
-                       else if (c->object.direction > c->object.i_direction)
-                               c->object.direction--;
-                       if (c->object.thrust < c->object.i_thrust)
-                               c->object.thrust++;
-                       else if (c->object.thrust > c->object.i_thrust)
-                               c->object.thrust--;
-
-                       /*
-                        * Translate object x/y position according to
-                        * trust/direction.  When reaching borders we simply
-                        * bounce for now.
-                        * (I need to review my trigonometry a bit again :)
-                        */
-                       /* XXX */
-                       c->object.x += 1 - (random() & 2);
-                       if (c->object.x < 0)
-                               c->object.x = 0;
-                       else if (c->object.x > WORLD_X_MAX - 1)
-                               c->object.x = WORLD_X_MAX - 1;
-                       c->object.y += 1 - (random() & 2);
-                       if (c->object.y < 0)
-                               c->object.y = 0;
-                       else if (c->object.y > WORLD_Y_MAX - 1)
-                               c->object.y = WORLD_Y_MAX - 1;
-               }
-
-               /* Send update frame information packets */
-               DLIST_FOREACH(&clients_list, nod) {
-                       client_t        *c = (client_t *)nod;
-                       node_t          *nod2;
-
-                       /*
-                       if (!c->authenticated)
-                               continue;
-                        */
-
-                       DLIST_FOREACH(&clients_list, nod2) {
-                               if (spacket_position_send(c,
-                                   &((client_t *)nod2)->object) == -1)
-                                       break;
-                       }
-                       (void) sendq_flush(&c->sendq, -1);
-               }
-       }
-}
-
-
-int
-spacket_auth_send(client_t *c)
-{
-       struct spacket_auth     p;
-
-       p.packet_type = BYTEORDER_NETWORK16(SPACKET_AUTH);
-       mm_memclr(p.string, 32);
-       mm_strncpy(p.string, SERVER_STRING, 31);
-       p.protocol_version = BYTEORDER_NETWORK16(SERVER_VERSION);
-       /* XXX */
-
-       return client_write(c, (uint8_t *)&p, sizeof(p), 0);
-}
-
-int
-spacket_pong_send(client_t *c)
-{
-       struct spacket_pong     p;
-
-       p.packet_type = BYTEORDER_NETWORK16(SPACKET_PONG);
-
-       return client_write(c, (uint8_t *)&p, sizeof(p), 0);
-}
-
-int
-spacket_position_send(client_t *c, object_t *o)
-{
-       struct spacket_position p;
-
-       p.packet_type = BYTEORDER_NETWORK16(SPACKET_POSITION);
-       p.object_id = p.object_type = BYTEORDER_NETWORK16(0);   /* XXX */
-       p.x = BYTEORDER_NETWORK16(o->x);
-       p.y = BYTEORDER_NETWORK16(o->y);
-       p.direction - BYTEORDER_NETWORK16(o->direction);
-
-       return client_write(c, (uint8_t *)&p, sizeof(p), 1);
-}
-
-
-/* Note that only the packet_type field is endian converted yet. */
-
-static int
-cpacket_auth_handler(client_t *c, uint16_t *ptr)
-{
-       struct cpacket_auth     *p = (struct cpacket_auth *)ptr;
-
-       p->protocol_version = BYTEORDER_HOST16(p->protocol_version);
-
-       if (c->authenticated || p->protocol_version < SERVER_VERSION)
-               return -1;
-
-       /*
-        * XXX For now.  Eventually also check user/password
-        * We could use APOP-like authentication where server sends random
-        * data as part of the authentication greeting/request, and expect
-        * client to append password to random data and send hashed result.
-        * We also should do user concurrency checking here.
-        */
-       c->authenticated = 1;
-
-       return 0;
-}
-
-/*
- * Note: Following function is never used, since pings are handled in the
- * kqueue main loop code.
- */
-/* ARGSUSED */
-static int
-cpacket_ping_handler(client_t *c, uint16_t *ptr)
-{
-       /* NOOP */
-
-       return 0;
-}
-
-static int
-cpacket_pong_handler(client_t *c, uint16_t *ptr)
-{
-/*     struct cpacket_pong     *p = (struct cpacket_pong *)ptr;*/
-
-       /* XXX */
-
-       return 0;
-}
-
-static int
-cpacket_direction_handler(client_t *c, uint16_t *ptr)
-{
-       struct cpacket_direction        *p = (struct cpacket_direction *)ptr;
-
-       p->direction = BYTEORDER_HOST16(p->direction);
-
-       /* Radians */
-       if (p->direction < 0 || p->direction > 1000)
-               return -1;
-
-       c->object.i_direction = p->direction;
-
-       return 0;
-}
-
-static int
-cpacket_thrust_handler(client_t *c, uint16_t *ptr)
-{
-       struct cpacket_thrust   *p = (struct cpacket_thrust *)ptr;
-
-       p->thrust = BYTEORDER_HOST16(p->thrust);
-
-       if (p->thrust < 0 || p->thrust > 20)
-               return -1;
-
-       c->object.i_thrust = p->thrust;
-
-       return 0;
-}
-
-static int
-cpacket_torp_handler(client_t *c, uint16_t *ptr)
-{
-/*     struct cpacket_torp     *p = (struct cpacket_torp *)ptr;*/
-
-       /* XXX */
-
-       return 0;
-}
-
-/* ARGSUSED */
-static int
-cpacket_quit_handler(client_t *c, uint16_t *ptr)
-{
-
-       return -1;
-}
diff --git a/tests/kqueue/packets.h b/tests/kqueue/packets.h
deleted file mode 100644 (file)
index ea668d1..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/* $Id: packets.h,v 1.9 2006/04/03 20:37:51 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * All packets must begin with an int16_t packet_type.  All fields of a packet
- * must either be [u]int8_t, [u]int16_t, [u]int32+t or [u]int64_t.  Moreover,
- * all fields will be passed in network/big endian byte order when sent over
- * the network.  We could have used a union, but this would have resulted in
- * larger, fixed sized packets wasting bandwidth.  Since a server to client
- * update will generally involve sending more than one such packet in a row,
- * it is important to minimize their size.
- * Note: If using 32-bit fields within a packet, make sure that they are
- * 32-bit aligned.
- */
-
-
-
-#ifndef _PACKETS_H_
-#define _PACKETS_H_
-
-
-
-#include <sys/types.h>
-
-#include "client.h"
-
-
-
-/*
- * For every server packet type we support, an index array will be used
- * with this structure to call the associated handler function, which will
- * perform sanity checking and process the packet, returning 0 on success or
- * -1 on error.  The size field will allow to perform sanity checking on
- * data size prior to calling the handler function, as well as to increase the
- * buffer pointer.
- */
-struct packet_index {
-       size_t  size;
-       int     (*handler)(client_t *, uint16_t *);
-};
-
-
-
-/*
- * Server to client packets
- */
-
-enum spacket_types {
-       SPACKET_AUTH = 0,
-       SPACKET_PING,
-       SPACKET_PONG,
-       SPACKET_POSITION,
-       SPACKET_COLLISION,
-       SPACKET_MAX
-};
-
-/* Used to request client authentication and respond success/failure */
-struct spacket_auth {
-       int16_t packet_type;
-       int16_t protocol_version;
-       char    string[32];
-       /* XXX */
-} __attribute__((__packed__));
-
-/* And for server to test idle connections */
-struct spacket_ping {
-       int16_t packet_type;
-} __attribute__((__packed__));
-
-/* And clients to test latency */
-struct spacket_pong {
-       int16_t packet_type;
-} __attribute__((__packed__));
-
-/* Object position/direction update to client */
-struct spacket_position {
-       int16_t packet_type;
-       int16_t object_id, object_type;
-       int16_t x, y, direction;
-} __attribute__((__packed__));
-
-/* Collision/detonation update to client */
-struct spacket_collision {
-       int16_t packet_type;
-       int16_t collision_type;
-       int16_t object1_id, object2_id;
-} __attribute__((__packed__));
-
-
-
-/*
- * Client to server packets
- */
-
-enum cpacket_tyoes {
-       CPACKET_AUTH = 0,
-       CPACKET_PING,
-       CPACKET_PONG,
-       CPACKET_DIRECTION,
-       CPACKET_THRUST,
-       CPACKET_TORP,
-       CPACKET_QUIT,
-       CPACKET_MAX
-};
-
-/* Used to respond to server authentication request */
-struct cpacket_auth {
-       int16_t packet_type;
-       int16_t protocol_version;
-       char    string[32];
-       /* XXX */
-} __attribute__((__packed__));
-
-/* To ping server for latency mesurement */
-struct cpacket_ping {
-       int16_t packet_type;
-} __attribute__((__packed__));
-
-/* To respond to server ping requests */
-struct cpacket_pong {
-       int16_t packet_type;
-} __attribute__((__packed__));
-
-/* Angle/direction change request */
-struct cpacket_direction {
-       int16_t packet_type;
-       int16_t direction;
-} __attribute__((__packed__));
-
-/* Speed change request */
-struct cpacket_thrust {
-       int16_t packet_type;
-       int16_t thrust;
-} __attribute__((__packed__));
-
-/* Torpedo fire request */
-struct cpacket_torp {
-       int16_t packet_type;
-       int16_t direction;
-} __attribute__((__packed__));
-
-/* Game quit request */
-struct cpacket_quit {
-       int16_t packet_type;
-} __attribute__((__packed__));
-
-
-
-void           update(void);
-int            spacket_auth_send(client_t *);
-int            spacket_pong_send(client_t *);
-int            spacket_position_send(client_t *, object_t *);
-
-
-
-#endif
diff --git a/tests/kqueue/recvq.c b/tests/kqueue/recvq.c
deleted file mode 100644 (file)
index 663ecba..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* $Id: recvq.c,v 1.5 2006/04/05 09:19:16 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include "recvq.h"
-
-
-
-int
-recvq_init(recvq_t *q, int fd, size_t size)
-{
-
-       if ((q->buffer = malloc(size)) == NULL)
-               return -1;
-
-       q->fd = fd;
-       q->size = size;
-       q->tail = 0;
-
-       return 0;
-}
-
-void
-recvq_destroy(recvq_t *q)
-{
-
-       free(q->buffer);
-}
-
-int
-recvq_read(recvq_t *q, int16_t **buf, size_t *size)
-{
-       ssize_t s;
-
-       if (q->tail == q->size)
-               return -1;
-
-       if (((s = read(q->fd, &q->buffer[q->tail], q->size - q->tail)) == -1 &&
-           errno != EAGAIN) || s == 0)
-               return -1;
-
-       /*
-        * Verify that s is a multiple of 2 before accepting it.  This will
-        * allow all packets and their fields to be 16-bit aligned.
-        */
-       if (((uint16_t)s & 1) != 0) {
-               syslog(LOG_NOTICE, "Uneven packet from %d", q->fd);
-               return -1;
-       }
-
-       *buf = (int16_t *)&q->buffer[q->tail];
-       *size = s;
-       q->tail += s;
-
-       return 0;
-}
-
-/*
- * Useful to discard ping packets which we process on the fly
- */
-void
-recvq_rewind(recvq_t *q, size_t size)
-{
-
-       if (q->tail >= size)
-               q->tail -= size;
-}
-
-void
-recvq_content(recvq_t *q, uint8_t **buf, size_t *size)
-{
-
-       *buf = (uint8_t *)q->buffer;
-       *size = q->tail;
-       q->tail = 0;
-}
diff --git a/tests/kqueue/recvq.h b/tests/kqueue/recvq.h
deleted file mode 100644 (file)
index 54e6eee..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* $Id: recvq.h,v 1.4 2006/04/03 20:37:51 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#ifndef _RECVQ_H_
-#define _RECVQ_H_
-
-
-
-#include <sys/types.h>
-
-
-
-typedef struct recvq {
-       int     fd;
-       uint8_t *buffer;
-       size_t  size, tail;
-} recvq_t;
-
-
-
-int    recvq_init(recvq_t *, int, size_t);
-void   recvq_destroy(recvq_t *);
-int    recvq_read(recvq_t *, int16_t **, size_t *);
-void   recvq_rewind(recvq_t *, size_t);
-void   recvq_content(recvq_t *, uint8_t **, size_t *);
-
-
-
-#endif
diff --git a/tests/kqueue/sendq.c b/tests/kqueue/sendq.c
deleted file mode 100644 (file)
index 7ea0052..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/* $Id: sendq.c,v 1.5 2006/04/03 20:37:51 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <sys/types.h>
-#include <sys/event.h>
-#include <sys/time.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <mmlist.h>
-#include <mmstring.h>
-
-#include "sendq.h"
-
-
-
-/*
- * Initializes a sendq object, allocating the queue buffer
- */
-int
-sendq_init(sendq_t *q, int fd, size_t size)
-{
-
-       if ((q->buffer = malloc(size)) == NULL)
-               return -1;
-
-       q->fd = fd;
-       q->size = size;
-       q->head = q->tail = 0;
-
-       return 0;
-}
-
-/*
- * Destroys a sendq object, freeing the queue buffer
- */
-void
-sendq_destroy(sendq_t *q)
-{
-
-       free(q->buffer);
-}
-
-/*
- * Attempts to write to the non-blocking socket.  In the case of a partial
- * write, queue the remaining of the buffer.  In case where the buffer is
- * full, return an error (-1), in which case the sendq has been exceeded and
- * client should be dropped.  We only write(2) if there is no pending buffers
- * already, of course.  If bfunc is not NULL, it will be called with passed
- * argument bfuncarg whenever data that couldn't be written immediately is
- * buffered.  If buffer is true, no attempt will be made at a real write; Data
- * will simply be buffered if possible.
- *
- * XXX There is a potential problem where if the client is lagged enough to
- * have filled the buffer, although not enough to exceed the queue but that
- * the client cannot recoup, we could consider the queue filled and drop the
- * client.  This because we aren't really using a real FIFO buffer.  This code
- * should probably use the mmfifo(3) library after the multiple bytes buffer
- * functions in it have been debugged and tested properly.
- * However, since if the user was this behind this would in practice mean that
- * his commands would take a while to be reflected, this is probably okay for
- * the time being.
- */
-int
-sendq_write(sendq_t *q, uint8_t *buf, size_t size,
-    void (*bfunc)(void *), void *bfuncarg, int buffer)
-{
-
-       /* Sendq empty?  Attempt to write(2) immediately */
-       if (!buffer && q->head == q->tail) {
-               ssize_t s;
-
-               /* Only allow EAGAIN */
-               if ((s = write(q->fd, buf, size)) == -1 && errno != EAGAIN)
-                       return -1;
-
-               /*
-                * If we wrote everything, simply return successfuly.
-                * Otherwise, fix our arguments to the unwritten buffer.
-                */
-               if (s == size)
-                       return 0;
-               else {
-                       size -= s;
-                       buf += s;
-               }
-       }
-
-       /*
-        * If the sendq buffer wasn't empty, or that there remains bytes
-        * after a partial write(2), queue the buffer if there's enough room.
-        * If there isn't enough room, return error.  If a function was
-        * supplied with an argument, also call this function if we buffer
-        * data.  This may allow our caller to enable back write polling
-        * events for this descriptor.
-        */
-       if (size > 0) {
-               if (q->tail + size > q->size)
-                       return -1;
-
-               (void) mm_memcpy(&q->buffer[q->tail], buf, size);
-               q->tail += size;
-               if (bfunc != NULL)
-                       bfunc(bfuncarg);
-       }
-
-       return 0;
-}
-
-/*
- * If any pending buffers exist, attempts to write them.  In the case of an
- * error, returns -1, in which case the client should be dropped.  If there
- * still remains unflushed data, 1 is returned.  Otherwise, 0 is.
- */
-int
-sendq_flush(sendq_t *q, size_t room)
-{
-
-       if (q->head != q->tail) {
-               ssize_t ns;
-               size_t  os = q->tail - q->head;
-
-               /* Only attempt write(2) syscall if there is room */
-               if (room == 0)
-                       return 1;
-
-               if ((ns = write(q->fd, &q->buffer[q->head], os)) == -1) {
-                       if (errno == EAGAIN)
-                               return 1;
-                       else
-                               return -1;
-               }
-
-               if ((q->head += ns) == q->tail)
-                       q->head = q->tail = 0;
-               else
-                       return 1;
-       }
-
-       return 0;
-}
diff --git a/tests/kqueue/sendq.h b/tests/kqueue/sendq.h
deleted file mode 100644 (file)
index 022543f..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* $Id: sendq.h,v 1.5 2006/04/03 20:37:51 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#ifndef _SENDQ_H_
-#define _SENDQ_H_
-
-
-
-#include <sys/types.h>
-
-#include <mmlist.h>
-
-
-
-typedef struct sendq {
-       int     fd;
-       uint8_t *buffer;
-       size_t  size, head, tail;
-} sendq_t;
-
-
-
-int    sendq_init(sendq_t *, int, size_t);
-void   sendq_destroy(sendq_t *);
-int    sendq_write(sendq_t *, uint8_t *, size_t, void (*)(void *), void *,
-           int);
-int    sendq_flush(sendq_t *, size_t);
-
-
-
-#endif
diff --git a/tests/memory/README b/tests/memory/README
deleted file mode 100644 (file)
index 52e022f..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-$Id: README,v 1.1 2005/11/14 01:55:20 mmondor Exp $
-
-The goal of this project is to create new memory allocation functions
-which can work on arbitrary pools of memory, while making sure to always
-favor low, already used pages.
-
-For instance, let's consider the case where multiple processes need to
-use a fair amount of shared memory.  The master process can allocate a
-region of memory using mmap(2) with MAP_ANON, making sure to use a large
-enough block that'll ever be used by the application.  This region can
-be shared.
-
-UVM lazily allocates pages which need to be accessed on-the-fly. This
-means that we must use a system similar to brk(2)/sbrk(2) and favor reusing
-already allocated memory in order to avoid the application growing too much.
-The process stack is for instance allocated this way;  A single very large
-region is mapped, and the actual memory in use increases with the process'
-requirements for more stack space.  In the case of stacks, since they are
-indeed stacks, the growing problem is not critical and easily determined.
-
-In the case of a general purpose memory allocator, this is more complex.
-mmpool(3) library allows to allocate fixed sized objects efficiently and
-makes sure to favor recently used pages in the allocations, which is okay.
-However, mmpool(3) must also be given allocation/freeing functions which
-it must use to allocate more pages as needed, or to free pages which haven't
-been used for some time.  This is where the general purpose allocators
-are used.
-
-In the case where a whole fixed large region can be used to allocate a single
-type of objects, we can simply use mmpool(3) and let it manage the large
-memory page.  However, needing to allocate a new memory segment per memory
-pool or object type appears problematic in some situations.  Moreover, being
-able to use a single large region for shared memory, another one for
-process-specific or shared mlocked memory per application, makes things
-easier.  It also allows server administrators to more easily modify various
-parameters relating to application scalibility.
-
-So this general purpose memory allocator should work on arbitrary regions
-of memory, and should automatically perform any necessary locking for
-synchronization.  This is quite similar to the libmm library in use by the
-Apache server.  This however should be released under BSD license, and
-especially favor reusing of previously allocated pages.
diff --git a/tests/pthread_utils/GNUmakefile b/tests/pthread_utils/GNUmakefile
deleted file mode 100644 (file)
index dd75e9c..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-# $Id: GNUmakefile,v 1.5 2005/11/22 09:24:42 mmondor Exp $
-
-MMLIB_PATH := ../../mmlib
-MMLIBS := $(addprefix ${MMLIB_PATH}/,mmlog.o mmpool.o mmstring.o)
-OBJS := mm_pthread_msg.o mm_pthread_sleep.o mm_pthread_pool.o mm_pthread_poll.o
-BINS := tests/msg_test tests/poll_test
-
-CFLAGS += -Wall
-#CFLAGS += -DDEBUG -DPTHREAD_DEBUG -g3
-
-LDFLAGS += -lc -lpthread
-#LDFLAGS += -lpthread_dbg
-
-
-all: $(BINS)
-
-
-%.o: %.c
-       cc -c ${CFLAGS} -I. -I$(MMLIB_PATH) -o $@ $<
-
-
-tests/msg_test: tests/msg_test.o $(MMLIBS) $(OBJS)
-       cc ${CFLAGS} -o $@ $@.c $(OBJS) -I. -I$(MMLIB_PATH) ${LDFLAGS} \
-               $(MMLIBS)
-
-tests/poll_test: tests/poll_test.o $(MMLIBS) $(OBJS)
-       cc ${CFLAGS} -o $@ $@.c $(OBJS) -I. -I$(MMLIB_PATH) ${LDFLAGS} \
-               $(MMLIBS)
-
-
-install: all
-
-
-clean:
-       rm -f tests/msg_test.o tests/poll_test.o $(BINS) $(OBJS) $(MMLIBS)
diff --git a/tests/pthread_utils/README b/tests/pthread_utils/README
deleted file mode 100644 (file)
index 8054ac7..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-This library is an attempt to provide pth library like API to NetBSD SA
-threads and kqueue.
-
-What we find are missing from the POSIX standard are added here:
-
-- Implementation of efficient messages to communicate among threads. These
-  messages are queued using an efficient pointer linking mechanism. It must be
-  possible for a thread to wait for messages while sleeping and to be awaken
-  when a message is available. It also must be possible to observe a maximum
-  timeout to wait for.
-- Implementation of filedescriptors and above mentionned thread messages
-  notification multiplexing, with support for timer. An example of this is
-  pth library's pth_poll_ev(). A timer event can interrupt thread-safe
-  filedescriptor polling, as well as thread messages arriving on a port.
-
-We beleive that it is possible to implement this using the kqueue(2)/kevent(2)
-system. The new call would be similar to:
-
-pthread_poll(struct pollfd *fds, int nfds,
-       struct pthread_port *ports, int nports,
-       struct pthread_sigs *sigs, int nsigs,
-       struct pthread_timers *timers, int ntimers)
-
-or similar system. This would allow multiplexing of various events into a
-single application loop.
-
-
-pthread_cond_timedwait() seems especially useful, either with a signal handler
-or perhaps using kqueue concurrently... pthread_cond_timedwait() will allow
-processes to wait for message arrival though a port, while
-pthread_cond_signal() or pthread_cond_broadcast() will be able to awaken them
-as messages are queued to the message port. However, we would ideally want to
-only signal a wanted thread waiting for a port... But, normally only one
-thread should be listening for messages on any given port. I have to see what
-I'll do for a thread listening for messages on multiple ports at a time...
-Perhaps that multiple ports could use the same conditional wait variable so
-that the process would only wait on that one, and then verify the message
-queue for each before going back in waiting mode.
-
-
-TODO:
-====
-- Replace mutex and conditonal variable initializers, as well as attributes,
-  with static initializers.
-- Provide similar static intializer macros as part of our API where possible.
-- I have a working message passing implementation, with possibility of a
-  waiter on as many ports as wanted. I however still have a challenge:
-  Multiplex system calls such as select(2), poll(2), connect(2) and accept(2)
-  with the messaging capability. One must be able to cause the other to
-  return. This could be tricky to properly implement. Maybe think about the
-  following ideas:
-  - Dedicate a thread to serve a syscall, with which communication is solely
-    done using messages. This however implies that only a single syscall at a
-    time can be processed by such a thread. This probably means that a pool of
-    such threads would become necessary. This also assumes that the syscall in
-    question do not block the whole process, but only the intended thread.
-    Alot of assumptions, but this would now work properly on all BSDs and
-    on Linux. Possibly also on Solaris.
-  - Use a mix of signals and syscalls, since signals can interrupt syscalls.
-    However, this implies adding capability in our message system to trigger
-    signals rather than only using a conditional variable to notify of message
-    arrival. This also probably means that the same signal handler must be
-    shared by the whole process, that is, all the threads.
-  - Use kqueue in a thread-safe manner with thread-specific signals (if
-    possible). kqueue can be used to track signals without the need for an
-    actual signal handler. It would also track filedescriptor changes at the
-    same time. This also probably means that we need to use kqueue user
-    events if possible, triggered from the message passing system. It also
-    means non-portable code outside of the realm of BSD systems.
-
-
-
-RECENT REVIEW AFTER SOME REFLECTION
-===================================
-
-Currently, pth_accept_ev() and pth_connect_ev() are the only two cases of
-special PTh functions which my software uses, notably mmftpd(8). These could
-easily be implemented using a random thread in the pool whenever necessary,
-with which communication would entirely use messages only. This thread could
-be told: Perform syscall in non-blocking mode using the supplied
-filedescriptor and notify me weither it succeeded, failed because of a timeout,
-if any, or was interrupted by a message event occuring on the specified ring,
-if any. The application however has to know that if it was interrupted by
-an event, the connection still occurs asynchroneously within the system.
-We should verify what could be done to cancel a not yet completed connection,
-if possible. This call could also report if the call was interrupted by a
-signal arrival (EINTR), optionally. If the socket was supplied in blocking
-mode, it would have to be switched to non-blocking mode by the system and
-then back into blocking mode. The caller could ensure to set it into
-non-blocking mode for enhanced performance if no blocking mode is required.
-The challenge would be finding a both efficient and portable solution to
-have select()/poll() awake upon reception of notification events on a ring.
-Perhaps that a global filedescriptor could be used for this, SOCK_DGRAM and
-one byte sent, or that a signal handler with a signal generation should be
-used... Both methods would probably awake the whole process, however.
-pthread_sigmask() could be used perhaps... I wouldn't want to have a special
-fd required for each ready thread of the pool, ideally.
-
-Implement:
-mm_pthread_io          pthread_poll_ev(), pthread_accept_ev(),
-                               pthread_connect_ev()
-mm_pthread_alarm       pthread_sleep(), etc.
-
-or maybe:
-
-mm_pthread_misc                For all of them
-
-Perhaps reimplement the system I worked on in mmserver(3) as well. This might
-be necessary for operations which really should be dedicated to a non-threaded
-process at occasions, and the subsystem should be available. It should probably
-use a pool using mmpool(3) as well, just like we are doing with threads.
-
-It would be interesting to implement better GC for mmpool(3)'s. Currently,
-pool_free() will discard pages which are no longer in use since some time,
-but the time cannot be linear, since it only accounts a certain number of
-calls made to it. It should instead be possible to use time intervals, and
-to let the application invoke the GC at wanted fixed intervals. This would
-allow to use time based average statistics rather than function call times
-based ones, without clobbering process or thread timers which the application
-might need. It simply has to provide its own and to call the GC function
-regularily.
-
-Hmm also, would be nice to be able to store the port_t pointer of the port
-which triggered notification on a ring_t, so that callers don't need to
-run through several ports attached on a ring... Maybe that it would be
-problematic however, since we can't guarantee atomicity between messages and
-messages processing, unless we kludged the whole thing with locks and lost
-efficiency. And because we only trigger notification to wakeup a waiting
-thread when a message is queued on an empty port, it's possible that the
-applicaton sleeps forever on a port if it didn't totally empty it, unless
-there was a way for the sleep function to immediately return if called on
-non-empty ports (as it's only alled on rings, and that rings don't have
-access to a list of ports in current implementation (only the ports can
-know which ring they are tied to)... I could implement something to have
-rings see their attached ports with a list, however. But this again means
-looping among ports to see if they're non-empty, heh, so why not let the
-application do it as they do now.
-
-
-
-IMPORTANT
-=========
-
-I did a test where multiple threads were polling on a single filedescriptor
-consisting of a socketpair, which other side was used to wake them up.
-Only one random thread would wake up.
-
-Using a signal to cause all threads to wake would not work either, because
-then again only a random thread will awake.
-
-It appears that the only way to ensure to wake wanted threads is using
-conditional variables and for them to only sleep on these.
-
-SIGIO possibility... threads would be sleeping on a conditional wait variable
-corresponding to the filedescriptor. For polling, the fd would be made in
-non-blocking I/O, with SIGIO sent to process. The fd and associated cond var
-would be added to a table. The SIGIO signal handler would need to check all
-fds in the set for possible I/O and awake corresponding threads waiting on
-cond var. A problem exists: How to check a filedescriptor for pending event?
-How to know if event is read or write, or hup, etc? Maybe using more ore less
-standard FION ioctls? poll/select with 0 timeout maybe, but that is still
-troublesome in terms of performance I beleive.
-
-fd     cond    interesting_events      occured_events?
-
-Hmm and what if a thread was allocated to start polling, and another wrapper
-thread wait for it sleeping on a cond var? Would it be sane to do this?
-When a timeout or message occurs however detected by the wrapper thread,
-how would we stop the other thread polling? We still have a problem.
-If we left pending polling threads, how would a future thread with successful
-polling on the same descriptor ever wake up, a random one would.
-Why does POSIX threads suck so much as to not provide any decent way to
-work with filedescriptors!? If at least I had pthread_signal() it would
-help. I could send a signal to interrupt the wanted thread when it was polling.
-Or if only there was a way to set the wanted signal mask for wanted processes
-as necessary, so that I would only have the wanted one process a particular
-signal I could send to interrupt it and then restore the masks, and do this
-somehow atomically. If POSIX had any of these requirements in mind while
-developing the standard, pthread_poll_condwait() or pthread_signal() would
-already exist anyways!
-
-
-HMM
-===
-
-A thread reserved for polling would seem best. We need to be able to interrupt
-that thread whenever needed using a signal, which all other processes must
-be blocking. We could use SIGIO, or SIGUSR2 for instance. That thread would
-process thread messages and go back to polling. It probably could handle
-timeouts as well, but this is probably not necessary. If it did, would
-probably free other threads from calling gettimeofday() too often. The thread
-has to remove the fd from the polling list when an event returned on it
-anyways, and so it could also send a reply message for timeout. It has to
-be interrupted anyways when a new fd is to be added, and this means that
-it could fix the poll timer before calling it each time to fit the soonest
-to expire fd... I could probably use kqueue too, or libevent in that thread
-to make it high performance as possible.
diff --git a/tests/pthread_utils/mm_pthread_debug.h b/tests/pthread_utils/mm_pthread_debug.h
deleted file mode 100644 (file)
index 2db67bc..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* $Id: mm_pthread_debug.h,v 1.2 2006/02/05 13:00:48 mmondor Exp $ */
-
-/*
- * Copyright (C) 2004-2005, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef MM_PTHREAD_DEBUG_H
-#define MM_PTHREAD_DEBUG_H
-
-
-
-#include <pthread.h>
-#include <syslog.h>
-
-
-
-#ifdef PTHREAD_DEBUG
-
-#define DEBUG_PTHREAD_ENTRY()  \
-       syslog(LOG_NOTICE, "> TID=%p FN=%s", pthread_self(), __func__)
-
-#define DEBUG_PTHREAD_EXIT()   \
-       syslog(LOG_NOTICE, "< TID=%p FN=%s", pthread_self(), __func__)
-
-#else
-#define DEBUG_PTHREAD_ENTRY()
-#define DEBUG_PTHREAD_EXIT()
-#endif
-
-
-
-#endif
diff --git a/tests/pthread_utils/mm_pthread_msg.c b/tests/pthread_utils/mm_pthread_msg.c
deleted file mode 100644 (file)
index d1fc7f0..0000000
+++ /dev/null
@@ -1,466 +0,0 @@
-/* $Id: mm_pthread_msg.c,v 1.14 2006/02/05 13:00:48 mmondor Exp $ */
-
-/*
- * Copyright (C) 2005, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * It is almost a shame that POSIX did not define a standard API for
- * inter-thread asynchroneous and synchroneous messaging.  So, here is my
- * implementation.  Note that for asynchroneous operation it is recommended to
- * use a memory pool such as mmpool(3) to allocate and free messages in an
- * efficient way, in cases where messages will need to be sent to the other
- * end without expecting a response back before the current function ends
- * (in which case a message obviously can't be on the stack).
- */
-
-
-
-#include <pthread.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h>
-
-#include <mmtypes.h>
-#include <mmlog.h>
-
-#include <mm_pthread_debug.h>
-#include <mm_pthread_msg.h>
-/*#include <mm_pthread_poll.h>*/
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2005\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mm_pthread_msg.c,v 1.14 2006/02/05 13:00:48 mmondor Exp $");
-
-
-
-/*
- * Allows to initialize a polling notification handle.  When attached to a
- * port, a message arriving on an empty port causes the associated ring to
- * wake the thread from pthread_ring_wait().
- */
-int
-pthread_ring_init(pthread_ring_t *ring)
-{
-       int     error;
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(ring != NULL && ring->magic != PRING_MAGIC);
-
-       if ((error = pthread_cond_init(&ring->cond, NULL)) == 0) {
-               if ((error = pthread_mutex_init(&ring->mutex, NULL)) == 0) {
-                       ring->magic = PRING_MAGIC;
-                       ring->event = ring->mevent = 0;
-                       DEBUG_PTHREAD_EXIT();
-                       return 0;
-               }
-               (void) pthread_cond_destroy(&ring->cond);
-       }
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Returns TRUE if the supplied ring is a valid/usable one, or FALSE
- * otherwise.  Useful to conditionally destroy it.
- */
-int
-pthread_ring_valid(pthread_ring_t *ring)
-{
-
-       DEBUG_PTHREAD_ENTRY();
-
-       DEBUG_PTHREAD_EXIT();
-       return (ring != NULL && ring->magic == PRING_MAGIC);
-}
-
-/*
- * Destroys a ring.  Note that all message ports attached to this ring should
- * first be detached or destroyed.
- */
-int
-pthread_ring_destroy(pthread_ring_t *ring)
-{
-       int     error;
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(ring != NULL && ring->magic == PRING_MAGIC);
-
-       if ((error = pthread_mutex_destroy(&ring->mutex)) == 0)
-               error = pthread_cond_destroy(&ring->cond);
-       ring->magic = 0;
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Causes the current thread to sleep until a message arrives on an empty port
- * associated with this ring.  In normal operation, a thread only goes in wait
- * mode after it processed all queued messages on all interesting ports.
- * However, provision is made so that a the function returns immediately if
- * messages already were received on a port attached to this ring since the
- * last call to pthread_ring_wait().
- * Although using such an absolute time timespec might be disadvantageous for
- * the API compared to a timeout in milliseconds for instance, this was chosen
- * to remain API-compatible with pthread_cond_timedwait(), and upwards
- * compatible with systems where nanosecond precision can be achieved.
- */
-int
-pthread_ring_wait(pthread_ring_t *ring, const struct timespec *abstime)
-{
-       int     error = 0;
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(ring != NULL && ring->magic == PRING_MAGIC);
-
-       /* We must hold the condition variable's mutex */
-       if (pthread_mutex_lock(&ring->mutex) != 0) {
-               error = -1;
-               goto err;
-       }
-
-       /* As long as we don't have confirmation that we must stop waiting */
-       for (ring->event = 0; ring->mevent == 0 &&
-           !ring->event && error == 0; ) {
-               /*
-                * Wait on conditional variable, which will automatically
-                * and atomically release the mutex and return with the mutex
-                * locked again, as soon as the conditional variable gets
-                * signaled.
-                */
-               if (abstime != NULL) {
-                       error = pthread_cond_timedwait(&ring->cond,
-                           &ring->mutex, abstime);
-               } else
-                       error = pthread_cond_wait(&ring->cond, &ring->mutex);
-       }
-       ring->mevent = 0;
-
-       /*
-        * And we know that conditional waiting functions returned with mutex
-        * locked, so now release it back.
-        */
-       (void) pthread_mutex_unlock(&ring->mutex);
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Allows to wake up waiter(s) on the specified ring, which are sleeping
- * threads within pthread_ring_wait().  This can be used to simulate the
- * arrival of a message on an empty port.  Also useful to use rings as a
- * notification system only when no message passing is needed.
- */
-int
-pthread_ring_notify(pthread_ring_t *ring)
-{
-       int     error;
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(ring != NULL && ring->magic == PRING_MAGIC);
-
-       if ((error = pthread_mutex_lock(&ring->mutex)) == 0) {
-               ring->mevent++;
-               ring->event = 1;
-               (void) pthread_cond_signal(&ring->cond);
-               (void) pthread_mutex_unlock(&ring->mutex);
-       }
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Allows to initialize/create a message port.
- */
-int
-pthread_port_init(pthread_port_t *port)
-{
-       int     error;
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(port != NULL && port->magic != PPORT_MAGIC);
-
-       if ((error = pthread_mutex_init(&port->lock, NULL)) != 0)
-               goto err;
-
-       port->magic = PPORT_MAGIC;
-       port->ring = NULL;
-       DLIST_INIT(&port->messages);
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Returns TRUE if the supplied port is valid/usable, or FALSE otherwise.
- * Useful to conditionally destroy a port, for instance.
- */
-int
-pthread_port_valid(pthread_port_t *port)
-{
-
-       DEBUG_PTHREAD_ENTRY();
-
-       DEBUG_PTHREAD_EXIT();
-       return (port != NULL && port->magic == PPORT_MAGIC);
-}
-
-/*
- * Destroys the specified port, previously created using pthread_port_init().
- */
-int
-pthread_port_destroy(pthread_port_t *port)
-{
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(port != NULL && port->magic == PPORT_MAGIC);
-
-       port->magic = 0;
-
-       DEBUG_PTHREAD_EXIT();
-       return pthread_mutex_destroy(&port->lock);
-}
-
-/*
- * Attaches a port to a ring.  Multiple ports may be attached to a ring.  A
- * message arriving on an empty port will cause the attached ring to be
- * notified, if any, and as such to cause a thread waiting on the ring to
- * be awakened.
- */
-int
-pthread_port_set_ring(pthread_port_t *port, pthread_ring_t *ring)
-{
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(port != NULL && port->magic == PPORT_MAGIC &&
-           (ring == NULL || ring->magic == PRING_MAGIC));
-
-       port->ring = ring;
-
-       DEBUG_PTHREAD_EXIT();
-       return 0;
-}
-
-/*
- * Allows to initialize a message before it can be sent over a port.  The
- * message only needs to be initialized once in general, even if it will be
- * used for bidirectional transmission for synchronous operation.  If the
- * reply port needs to be changed, however, this function should be used again
- * to set the new reply port.
- */
-int
-pthread_msg_init(pthread_msg_t *msg, pthread_port_t *rport)
-{
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(msg != NULL && msg->magic != PMESG_MAGIC &&
-           (rport == NULL || rport->magic == PPORT_MAGIC));
-
-       msg->magic = PMESG_MAGIC;
-       msg->reply = rport;
-       msg->size = 0;
-       msg->message = NULL;
-
-       DEBUG_PTHREAD_EXIT();
-       return 0;
-}
-
-/*
- * Returns TRUE if supplied message is valid/usable or FALSE otherwise.
- */
-int
-pthread_msg_valid(pthread_msg_t *msg)
-{
-
-       DEBUG_PTHREAD_ENTRY();
-
-       DEBUG_PTHREAD_EXIT();
-       return (msg != NULL && msg->magic == PMESG_MAGIC);
-}
-
-/*
- * Invalidates a message, so that it can no longer be sent over ports.
- */
-int
-pthread_msg_destroy(pthread_msg_t *msg)
-{
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(msg != NULL && msg->magic == PMESG_MAGIC);
-
-       msg->magic = 0;
-
-       DEBUG_PTHREAD_EXIT();
-       return 0;
-}
-
-/*
- * If any message exists in the queue of the specified port, unqueues it and
- * returns it.  Otherwise, NULL is returned.  In normal operation, all messages
- * queued to a port are processed before putting the thread back into sleep,
- * mainly for efficiency, but also because it eases synchronization.
- */
-pthread_msg_t *
-pthread_msg_get(pthread_port_t *port)
-{
-       pthread_msg_t   *msg = NULL;
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(port != NULL && port->magic == PPORT_MAGIC);
-
-       if (pthread_mutex_lock(&port->lock) != 0)
-               goto err;
-
-       if ((msg = DLIST_TOP(&port->messages)) != NULL) {
-               DEBUG_ASSERT(msg->magic == PMESG_MAGIC);
-               DLIST_UNLINK(&port->messages, (node_t *)msg);
-       }
-
-       (void) pthread_mutex_unlock(&port->lock);
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return (pthread_msg_t *)msg;
-}
-
-/*
- * Queues the specified message to the specified port, returning 0 on success.
- * Note that the message data is not copied or moved, but that a pointer
- * system is used to queue the message.  Thus, the message's shared memory
- * region is leased temporarily to the other end.  One has to be careful to
- * not allocate this message space on the stack when asynchroneous operation
- * is needed.  In synchroneous operation mode, it is not a problem, since the
- * sender does not have to modify the data until the other end replies back
- * with the same message after modifying the message if necessary.  In
- * synchroneous mode, we simply delegate that message memory region to the
- * other end until it notifies us with a reply that it is done working with
- * it.  Returns 0 on success, or an error number.
- */
-int
-pthread_msg_put(pthread_port_t *port, pthread_msg_t *msg)
-{
-       int     error = 0;
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(port != NULL && port->magic == PPORT_MAGIC &&
-           msg != NULL && msg->magic == PMESG_MAGIC);
-
-       if ((error = pthread_mutex_lock(&port->lock)) != 0)
-               goto err;
-
-       DLIST_APPEND(&port->messages, (node_t *)msg);
-       if (port->ring != NULL) {
-               if (DLIST_NODES(&port->messages) == 1) {
-                       /*
-                        * We know that there previously were no messages,
-                        * and that the reading thread then waits for any
-                        * message to be available.  Signal it that there at
-                        * least is one message ready.  The other end should
-                        * normally process all available messages before
-                        * going back into waiting.
-                        */
-                       if ((error = pthread_mutex_lock(&port->ring->mutex))
-                           == 0) {
-                               port->ring->event = 1;
-                               (void) pthread_cond_signal(&port->ring->cond);
-                               (void) pthread_mutex_unlock(
-                                   &port->ring->mutex);
-                       }
-               }
-               /*
-                * If the other end, however, is already locked
-                * waiting for the ring to be notified while
-                * there already are messages, we still trigger mevent
-                * to cause it to unlock, however.  This behavior is
-                * useful in the polling system code, for instance.
-                */
-               /* XXX We don't use a mutex for now... */
-               port->ring->mevent++;
-       }
-
-       (void) pthread_mutex_unlock(&port->lock);
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Meant to be used in synchroneous message transfer mode.  The initial sender
- * sends a message to the other end, which then uses this function to notify
- * back the initial sender that it is done, often with a success/failure
- * result as part of the message.  Returns 0 on success, or an error number.
- */
-int
-pthread_msg_reply(pthread_msg_t *msg)
-{
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(msg != NULL && msg->magic == PMESG_MAGIC &&
-           msg->reply != NULL);
-
-       DEBUG_PTHREAD_EXIT();
-       return pthread_msg_put(msg->reply, msg);
-}
-
-/*
- * Returns the number of pending messages tied to the port, if any, or -1
- * on error.
- */
-int
-pthread_port_pending(pthread_port_t *port)
-{
-       int     pending = -1;
-
-       DEBUG_PTHREAD_ENTRY();
-       DEBUG_ASSERT(port != NULL && port->magic == PPORT_MAGIC);
-
-       if (pthread_mutex_lock(&port->lock) != 0)
-               goto err;
-
-       pending = (int)DLIST_NODES(&port->messages);
-
-       (void) pthread_mutex_unlock(&port->lock);
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return pending;
-}
diff --git a/tests/pthread_utils/mm_pthread_msg.h b/tests/pthread_utils/mm_pthread_msg.h
deleted file mode 100644 (file)
index 287bc2e..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* $Id: mm_pthread_msg.h,v 1.3 2005/09/15 11:46:58 mmondor Exp $ */
-
-/*
- * Copyright (C) 2005, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef MM_PTHREAD_MSG_H
-#define MM_PTHREAD_MSG_H
-
-
-
-#include <pthread.h>
-
-#include <mmtypes.h>
-#include <mmlist.h>
-
-
-
-#define PRING_MAGIC    0x50524e47
-#define        PPORT_MAGIC     0x50505254
-#define PMESG_MAGIC    0x504d5347
-
-typedef struct {
-       u_int32_t       magic;
-       pthread_cond_t  cond;
-       pthread_mutex_t mutex;
-       int             mode;
-       int             event;
-       int             mevent;
-} pthread_ring_t;
-
-enum pthread_ring_modes {
-       PTHREAD_RMOD_NOWAIT,
-       PTHREAD_RMOD_CONDWAIT,
-       PTHREAD_RMOD_FDWAIT
-};
-
-typedef struct {
-       u_int32_t       magic;
-       pthread_ring_t  *ring;
-       pthread_mutex_t lock;
-       list_t          messages;
-} pthread_port_t;
-
-typedef struct {
-       node_t          node;
-       u_int32_t       magic;
-       pthread_port_t  *reply;
-       size_t          size;
-       void            *message;
-} pthread_msg_t;
-
-
-
-extern int             pthread_ring_init(pthread_ring_t *);
-extern int             pthread_ring_valid(pthread_ring_t *);
-extern int             pthread_ring_destroy(pthread_ring_t *);
-extern int             pthread_ring_wait(pthread_ring_t *,
-                           const struct timespec *);
-extern int             pthread_ring_notify(pthread_ring_t *);
-
-extern int             pthread_port_init(pthread_port_t *);
-extern int             pthread_port_valid(pthread_port_t *);
-extern int             pthread_port_destroy(pthread_port_t *);
-extern int             pthread_port_set_ring(pthread_port_t *,
-                           pthread_ring_t *);
-extern int             pthread_msg_init(pthread_msg_t *,
-                           pthread_port_t *);
-extern int             pthread_msg_valid(pthread_msg_t *);
-extern int             pthread_msg_destroy(pthread_msg_t *);
-extern pthread_msg_t   *pthread_msg_get(pthread_port_t *);
-extern int             pthread_msg_put(pthread_port_t *,
-                           pthread_msg_t *);
-extern int             pthread_msg_reply(pthread_msg_t *);
-extern int             pthread_port_pending(pthread_port_t *);
-
-
-
-#endif
diff --git a/tests/pthread_utils/mm_pthread_poll.c b/tests/pthread_utils/mm_pthread_poll.c
deleted file mode 100644 (file)
index 36508b4..0000000
+++ /dev/null
@@ -1,1116 +0,0 @@
-/* $Id: mm_pthread_poll.c,v 1.15 2006/02/05 13:00:48 mmondor Exp $ */
-
-/*
- * Copyright (C) 2005, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * I consider this code to be a major hack around the inherent problems unix
- * systems face because of the lack of support for filedescriptor polling in
- * the POSIX threads API.  Although pthread defines methods for thread
- * synchronization and polling waiting for events (using conditionnal
- * variables), and that unix provides polling on filedescriptors using
- * select(2), poll(2), kqueue(2) and other mechanisms, both are totally
- * distinct entities which can be considered to either conflict with
- * eachother or to not be related enough in a unified way.  The current
- * situation makes it almost impossible for a thread to both be polling for
- * interthread efficient messages implementations built upon pthread, and
- * filedescriptor events, concurrently.
- *
- * The GNU PTH library implements non-standard functions which allow to
- * multiplex interthread messages and filedescriptor events, using for
- * instance pth_poll_ev(), pth_select_ev(), pth_accept_ev(), pth_connect_ev(),
- * etc.  However, this is internally implemented using a single large select(2)
- * based loop along with a slow large loop looking for non-fd events based on
- * the principles of libevent.  This threading library has other disadventages,
- * such as not providing a preemptive scheduler (being a fully userspace
- * implementation) and not allowing to scale to multiple processors on SMP
- * systems.  This interface however shows how good the POSIX threads API could
- * have been, if it was better designed with unix systems in mind.  This
- * library also being the most portable threads library alternative for quite
- * some time, because of the fact that Operating Systems implemented POSIX
- * threads inconsistently, or not at all, caused us to use PTH during some
- * time to develop software in cases where a pool of processes was not ideal
- * because of the frequency of shared memory synchronization needs.
- *
- * With the advent of POSIX threads implementations on more unix and unix-like
- * systems and of modern implementations behaving more consistently, which can
- * scale on SMP systems and provide preemptive scheduling, it was considered
- * worthwhile for us to adapt our software again to use the standard POSIX
- * API.  Especially considering that NetBSD which had no OS provided threads
- * implementation for applications now has an awesome pthreads implementation
- * starting with version 2.0. However, we encountered difficulties with some
- * software which used the complex multiplexing of thread events and
- * filedescriptor ones.  This module provides a solution to port this software.
- * It however is somewhat a hack.
- *
- * The downsides of this implementation are as follows.  We originally intended
- * to develop a system which would scale among an increasing number of threads
- * in a ready pool of threads, scaling with concurrency of the polling calls.
- * This however proved difficult, or impossible to achieve, the main reasons
- * being that 1) A signal delivered to a process is only received by a random
- * thread that is not blocking it.  2) In the case where multiple threads are
- * polling on a common file descriptor, similarily only one random thread
- * is awaken.  3) pthread_cond_signal() and pthread_cond_broadcast() cannot
- * wake threads waiting in filedescriptor polling.  4) to achieve what we
- * needed, two descriptors would have been necessary per notification ring.
- * this was considered an aweful solution and was promptly rejected.  5) The
- * POSIX API does not define a way for a process to set or change the signal
- * blocking masks of other threads on the fly.
- *
- * Our solution then had to rely on a main descriptor polling manager thread
- * which would be used to poll file descriptors, and would as a device serve
- * client threads via efficient interthread messages.  An issue still arises
- * when a client thread sends a message to the polling thread to add new
- * descriptors for polling or to cancel polling and remove descriptors.
- * The polling thread must be able to immediately process these events
- * awaking from filedescriptor polling.  Two possible hacks could be used for
- * this.  1) Use an AF_LOCAL SOCK_DGRAM socketpair(), which one side would
- * be used to trigger an event writing some data, and the other side always
- * included by the polling thread within the set of descriptors.  2) Send a
- * signal to the process which only the polling thread is not blocking,
- * to ensure that it be the one catching it, as such to awake from polling
- * with an EINTR error code.  This second solution was considered more elegant
- * and is used as the basis of this implementation.  We currently are
- * clubbering the SIGUSR2 signal to achieve this.
- */
-
-
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <pthread.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <poll.h>
-#include <signal.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <mmtypes.h>
-#include <mmlog.h>
-#include <mmlist.h>
-
-#include <mm_pthread_debug.h>
-#include <mm_pthread_msg.h>
-#include <mm_pthread_pool.h>
-#include <mm_pthread_poll.h>
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2005\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mm_pthread_poll.c,v 1.15 2006/02/05 13:00:48 mmondor Exp $");
-
-
-
-/*
- * Synchroneous communications message between arbitrary threads and the
- * polling thread.  Since communication is synchroneous, we only need to
- * allocate one such message per thread.  We are always expecting a reply
- * back after sending a query before reusing the buffer.  In fact, the
- * message passing system only serves as a means for synchronization around
- * the message, which is a shared memory object.
- */
-struct poll_msg {
-       pthread_msg_t   msgnode;
-       /* Passed as parameters */
-       bool            cancel;
-       struct pollfd   *fds;
-       nfds_t          nfds;
-       int             timeout;
-       /* Returned as result */
-       int             ready, error;
-       /* Internally used */
-       struct timeval  expires;
-};
-
-/*
- * An index is maintained of descriptor number -> poll_msg_index
- * structures.  Each of wich has information on the message the descriptor
- * belongs to, and the index into the pollfd array so that it be easy to
- * efficiently do per-fd work.
- */
-struct poll_idx {
-       int             idx;
-       struct poll_msg *msg;
-};
-
-/*
- * Thread specific needed resources to use our special polling
- */
-struct poll_data {
-       pthread_port_t  port;
-       struct poll_msg msg;
-};
-
-
-
-#define                        POLLWAKE()      do {                            \
-       pollingevents++;                                                \
-       if (polling != 0)                                               \
-               (void) kill(process_id, SIGUSR2);                       \
-} while (/* CONSTCOND */0)
-
-
-
-/*
- * Static functions prototypes
- */
-static int             pthread_poll_proc_init(void);
-static void            pthread_poll_proc_init2(void);
-static int             pthread_poll_thread_init(struct poll_data **);
-static void            pthread_poll_thread_exit(void *);
-static void            *poll_thread(void *);
-static int             poll_thread_attach_fds(struct poll_msg *);
-static void            poll_thread_detach_fds(struct poll_msg *);
-static void            poll_thread_sighandler(int);
-
-/*
- * Static process specific storage
- */
-static bool            pthread_poll_initialized = FALSE;
-static pthread_once_t  pthread_poll_proc_initialized = PTHREAD_ONCE_INIT;
-static pthread_key_t   pthread_poll_proc_key;
-static pthread_ring_t  pthread_poll_thread_started_ring;
-static pthread_port_t  pthread_poll_thread_port;
-static pid_t           process_id;
-static int             polling = 0;
-static int             pollingevents = 0;
-
-/*
- * Static global poll_thread storage.  No synhronization is necessary when
- * using these, since only the polling thread does.
- */
-static struct poll_idx *poll_idx;
-static nfds_t          poll_idx_size;
-static struct pollfd   *poll_fds;
-static nfds_t          poll_fds_size;
-static nfds_t          poll_nfds;
-
-
-
-/*
- * Static internal functions
- */
-
-static int
-pthread_poll_proc_init(void)
-{
-       int                     error;
-       struct sigaction        act;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if ((error = pthread_key_create(&pthread_poll_proc_key,
-           pthread_poll_thread_exit)) != 0)
-               goto err;
-
-       act.sa_handler = poll_thread_sighandler;
-       act.sa_flags = 0;
-       (void) sigemptyset(&act.sa_mask);
-       (void) sigaddset(&act.sa_mask, SIGUSR2);
-       if (sigaction(SIGUSR2, &act, NULL) != 0) {
-               error = errno;
-               goto err;
-       }
-
-       process_id = getpid();
-
-       DEBUG_PTHREAD_EXIT();
-       return 0;
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-static void
-pthread_poll_proc_init2(void)
-{
-       int     error;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if ((error = pthread_poll_proc_init()) != 0) {
-               (void) fprintf(stderr, "pthread_poll_proc_init() - %s\n",
-                   strerror(error));
-               DEBUG_PTHREAD_EXIT();
-               exit(EXIT_FAILURE);
-       }
-
-       DEBUG_PTHREAD_EXIT();
-}
-
-static int
-pthread_poll_thread_init(struct poll_data **res)
-{
-       int                     error;
-       struct poll_data        *data;
-       sigset_t                set;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       (void) sigemptyset(&set);
-       (void) sigaddset(&set, SIGUSR2);
-       (void) pthread_sigmask(SIG_BLOCK, &set, NULL);
-
-       if ((data = malloc(sizeof(struct poll_data))) == NULL) {
-               error = ENOMEM;
-               goto err;
-       }
-
-       if ((error = pthread_port_init(&data->port)) != 0)
-               goto err;
-       if ((error = pthread_msg_init(&data->msg.msgnode, &data->port)) != 0)
-               goto err;
-
-       if ((error = pthread_setspecific(pthread_poll_proc_key, data)) != 0)
-               goto err;
-
-       *res = data;
-
-       DEBUG_PTHREAD_EXIT();
-       return 0;
-
-err:
-       if (data != NULL) {
-               (void) pthread_port_destroy(&data->port);
-               free(data);
-       }
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-static void
-pthread_poll_thread_exit(void *specific)
-{
-       struct poll_data        *data = (struct poll_data *)specific;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       (void) pthread_port_destroy(&data->port);
-       (void) pthread_msg_destroy(&data->msg.msgnode);
-       free(data);
-
-       /*
-        * Some implementations need this
-        */
-       (void) pthread_setspecific(pthread_poll_proc_key, NULL);
-
-       DEBUG_PTHREAD_EXIT();
-}
-
-
-/*
- * Actual polling thread, with which we communicate using messages polling on
- * pthread_port_t and pthread_ring_t.  This is the only thread that should be
- * catching SIGUSR2 signals (used to wake us up and reiterate our main loop.
- * Note: Although less efficient than using kqueue(2) or libevent(3), after
- * discussion with 3s4i we settled to using poll(2) for now, which minimizes
- * OS dependencies as well as third party software dependencies.  Because
- * pthread_poll_ring(2) is only sparsely used by our software (migrating from
- * using PTH library which provided pth_poll_ev()), and that we only provide
- * it small pollfd arrays, this implementation was considered to meet our
- * needs using poll(2). This also met the requirements for Tact group.
- */
-/* ARGSUSED */
-static void *
-poll_thread(void *args)
-{
-       sigset_t        set;
-       pthread_ring_t  ring;
-       list_t          msg_list;
-       register int    i;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       /*
-        * This initialization shouldn't fail.  If it did, it would be nice to
-        * be able to simply panic eventually. XXX
-        */
-
-       /*
-        * Create set for SIGUSR2 which we'll unblock/block
-        */
-       (void) sigemptyset(&set);
-       (void) sigaddset(&set, SIGUSR2);
-
-       /*
-        * Allocate an initial buffer size for our pollfd array as well as for
-        * our descriptor based index.  We'll double these buffers as
-        * necessary at runtime.
-        */
-       poll_fds_size = 64;
-       poll_fds = malloc(sizeof(struct pollfd) * poll_fds_size);
-       poll_nfds = 0;
-       poll_idx_size = 64;
-       poll_idx = malloc(sizeof(struct poll_msg) * poll_idx_size);
-       for (i = 0; i < poll_idx_size; i++)
-               poll_idx[i].msg = NULL;
-       DLIST_INIT(&msg_list);
-
-       /*
-        * Initialize message port and associated ring.  The message port is
-        * module global, so that it be public to pthread_poll_ring().
-        */
-       (void) pthread_port_init(&pthread_poll_thread_port);
-       (void) pthread_ring_init(&ring);
-       (void) pthread_port_set_ring(&pthread_poll_thread_port, &ring);
-
-       /*
-        * Notify parent that we're ready.
-        */
-       (void) pthread_ring_notify(&pthread_poll_thread_started_ring);
-
-       /*
-        * Main loop from which we never exit
-        */
-       for (;;) {
-               register int    n;
-               int             timeout;
-               struct timeval  tv, ttv;
-               struct poll_msg *msg, *nextmsg;
-
-               /*
-                * Get time of day in a rather high resolution.  We need to
-                * do this to be able to evaluate timeouts later on.  We
-                * attempt to only require one time syscall per loop.
-                */
-               (void) gettimeofday(&tv, NULL);
-
-               pollingevents = 0;
-
-               /*
-                * Process any messages.  We need to add the descriptors if
-                * they aren't already added.  Also store yet unsatisfied
-                * request messages into a list.
-                */
-               while ((msg = (struct poll_msg *)pthread_msg_get(
-                   &pthread_poll_thread_port)) != NULL) {
-                       if (msg->cancel) {
-                               /*
-                                * Immediately satisfy request on demand
-                                */
-                               msg->error = ECANCELED;
-                               DLIST_UNLINK(&msg_list, (node_t *)msg);
-                               poll_thread_detach_fds(msg);
-                               (void) pthread_msg_reply(&msg->msgnode);
-                               continue;
-                       }
-                       if (poll_thread_attach_fds(msg) == 0) {
-                               msg->ready = msg->error = 0;
-                               if (msg->timeout != -1) {
-                                       /*
-                                        * Convert millisecond timeout to an
-                                        * absolute time timeval
-                                        */
-                                       msg->expires.tv_sec = tv.tv_sec;
-                                       msg->expires.tv_usec = tv.tv_usec;
-                                       ttv.tv_sec = msg->timeout / 1000;
-                                       ttv.tv_usec = (msg->timeout % 1000)
-                                          * 1000;
-                                       timeradd(&msg->expires, &ttv,
-                                           &msg->expires);
-                               }
-                               DLIST_APPEND(&msg_list, (node_t *)msg);
-                       } else {
-                               msg->ready = 0;
-                               msg->error = EINVAL;
-                               (void) pthread_msg_reply(&msg->msgnode);
-                       }
-               }
-
-               /*
-                * Process timeouts.  For request messages which timed out,
-                * satisfy them immediately using ETIMEDOUT error.
-                * This also allows to evaluate which is the soonest to expire
-                * entry, which poll(2) will have to use as timeout.
-                */
-               ttv.tv_sec = ttv.tv_usec = 99999;
-               for (msg = DLIST_TOP(&msg_list); msg != NULL; msg = nextmsg) {
-                       nextmsg = DLIST_NEXT(msg);
-
-                       if (msg->timeout == -1)
-                               continue;
-                       if (timercmp(&msg->expires, &tv, <)) {
-                               msg->error = ETIMEDOUT;
-                               DLIST_UNLINK(&msg_list, (node_t *)msg);
-                               poll_thread_detach_fds(msg);
-                               (void) pthread_msg_reply(&msg->msgnode);
-                       } else if (timercmp(&msg->expires, &ttv, <)) {
-                               ttv.tv_sec = msg->expires.tv_sec;
-                               ttv.tv_usec = msg->expires.tv_usec;
-                       }
-               }
-
-               /*
-                * If there are no registered descriptors to poll for, wait
-                * using the thread friendly ring until messages occur, and
-                * reiterate.
-                */
-               if (poll_nfds == 0) {
-                       (void) pthread_ring_wait(&ring, NULL);
-                       continue;
-               }
-
-               /*
-                * Perform polling.  poll(2) for as much time as possible,
-                * although making sure to allow the soonest to expire query
-                * to stop polling.  Next to expire entry time is in ttv and
-                * current time in tv.  Calculate difference and convert to
-                * milliseconds.
-                */
-               if (ttv.tv_sec == 99999 && ttv.tv_usec == 99999)
-                       timeout = -1;
-               else {
-                       timersub(&ttv, &tv, &ttv);
-                       timeout = (ttv.tv_sec * 1000) + (ttv.tv_usec / 1000);
-               }
-
-               /*
-                * Unblock the SIGUSR2 signal, which we should be the only
-                * thread to receive, all other threads blocking it.
-                * Only leave it unblocked for the duration of the poll(2)
-                * syscall.  We cause our loop to reiterate in any case of
-                * error, EINTR or no file descriptor with pending event.
-                */
-               (void) pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-               polling++;
-
-               n = 0;
-               if (pollingevents != 0)
-                       goto unblock;
-
-               n = poll(poll_fds, poll_nfds, timeout);
-
-unblock:
-               polling--;
-               (void) pthread_sigmask(SIG_BLOCK, &set, NULL);
-               if (pollingevents != 0 || n < 1)
-                       continue;
-
-               /*
-                * Verify which descriptors have interesting events set,
-                * increasing events counter of corresponding requests.
-                */
-               for (i = 0; n != 0 && i < poll_nfds; i++) {
-                       if (poll_fds[i].revents != 0) {
-                               (poll_idx[poll_fds[i].fd].msg->ready)++;
-                               n--;
-                       }
-               }
-               /*
-                * Now verify pending request messages for events, and satisfy
-                * the requests of those who do.
-                */
-               for (msg = DLIST_TOP(&msg_list); msg != NULL; msg = nextmsg) {
-                       nextmsg = DLIST_NEXT(msg);
-
-                       if (msg->ready != 0) {
-                               /*
-                                * ready and error fields are already set
-                                */
-                               DLIST_UNLINK(&msg_list, (node_t *)msg);
-                               poll_thread_detach_fds(msg);
-                               (void) pthread_msg_reply(&msg->msgnode);
-                       }
-               }
-       }
-
-       /* NOTREACHED */
-       DEBUG_PTHREAD_EXIT();
-       pthread_exit(NULL);
-       return NULL;
-}
-
-/*
- * Permits to merge supplied pollfd set with the main set
- */
-static int
-poll_thread_attach_fds(struct poll_msg *msg)
-{
-       register int    i, fd, idx;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       for (i = 0; i < msg->nfds; i++) {
-               fd = msg->fds[i].fd;
-
-               /*
-                * Ignore unset descriptors
-                */
-               if (fd == -1)
-                       continue;
-
-               /*
-                * Grow index buffer if necessary.  Either grow by doubling
-                * size, or even more if necessary to hold index to fd.
-                * If we only grew to hold fd, we might need to realloc(3) too
-                * often.  Take care to also NULL msg field of new entries.
-                */
-               if (poll_idx_size <= fd) {
-                       struct poll_idx *idx;
-                       int             size, i2;
-
-                       size = poll_idx_size * 2;
-                       if (fd > size)
-                               size = fd;
-                       if ((idx = realloc(poll_idx,
-                           sizeof(struct poll_idx) * size)) == NULL)
-                               goto err;
-                       poll_idx = idx;
-                       for (i2 = poll_idx_size; i2 < size; i2++)
-                               poll_idx[i2].msg = NULL;
-                       poll_idx_size = size;
-               }
-
-               /*
-                * Error if descriptor not unique before adding to set.
-                * We do not allow multiple threads polling on the same
-                * descriptor at the same time in our system.  We would
-                * otherwise need to gracefully handle duplicates,
-                * multiplexing them, which isn't required at all by our
-                * applications.  So let's keep things simple.
-                */
-               if (poll_idx[fd].msg != NULL)
-                       goto err;
-
-               /*
-                * Resize pollfd array if needed.  Grow by doubling.
-                * This should happen very rarely.
-                * XXX We could check this condition only once at the
-                * top of this fonction and take in consideration the
-                * number of descriptors to add, if wanted for optimization.
-                */
-               if (poll_fds_size <= poll_nfds) {
-                       struct pollfd   *ptr;
-
-                       if ((ptr = realloc(poll_fds,
-                           sizeof(struct pollfd) * (poll_fds_size * 2)))
-                           == NULL)
-                               goto err;
-                       poll_fds = ptr;
-                       poll_fds_size *= 2;
-               }
-
-               /*
-                * Finally add descriptor to set and register it for indexing.
-                * We simply need to append it to the existing entries in our
-                * global polling set array.
-                */
-               idx = poll_nfds;
-               poll_fds[idx].fd = fd;
-               poll_fds[idx].events = msg->fds[i].events;
-               poll_fds[idx].revents = 0;
-               poll_idx[fd].msg = msg;
-               poll_idx[fd].idx = idx;
-               poll_nfds = ++idx;
-       }
-
-       DEBUG_PTHREAD_EXIT();
-       return 0;
-
-err:
-       (void) poll_thread_detach_fds(msg);
-
-       DEBUG_PTHREAD_EXIT();
-       return -1;
-}
-
-/*
- * Permits to disunite supplied pollfd set from the main set.  Also sets the
- * revents fields of the supplied set to the ones of the main set.
- */
-static void
-poll_thread_detach_fds(struct poll_msg *msg)
-{
-       register int    i, fd, idx;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       for (i = 0; i < msg->nfds; i++) {
-               fd = msg->fds[i].fd;
-
-               /*
-                * Make sure fd was properly registered
-                */
-               if (poll_idx[fd].msg != msg)
-                       continue;
-
-               /*
-                * Find index in global pollfd set for this fd
-                */
-               idx = poll_idx[fd].idx;
-
-               /*
-                * Update pollfd entry according to global one
-                */
-               msg->fds[i].revents = poll_fds[idx].revents;
-
-               /*
-                * Unlink fd from the global set.  The removal method is
-                * simple; Take the last entry of the global set and move it
-                * over the current entry, updating index links, and lower
-                * the gobal nfds by one.  If we're the last entry, simply
-                * remove it invalidating its index entry lowering the global
-                * nfds.
-                */
-
-               if (--poll_nfds != idx) {
-                       /*
-                        * Not last entry, move last entry over entry to
-                        * delete.
-                        */
-                       register struct pollfd  *deleted, *last;
-                       int                     deleted_fd, deleted_idx;
-
-                       last = &poll_fds[poll_nfds];
-                       deleted = &poll_fds[idx];
-                       deleted_fd = deleted->fd;
-                       deleted_idx = poll_idx[deleted_fd].idx;
-
-                        /* Copy last entry over deleted one */
-                       deleted->fd = last->fd;
-                       deleted->events = last->events;
-                       deleted->revents = last->revents;
-
-                       /*
-                        * Reindex last entry which was moved, don't touch
-                        * the msg pointer though.
-                        */
-                       poll_idx[last->fd].idx = deleted_idx;
-
-                       /* And finally invalidate last entry */
-                       poll_idx[deleted_fd].msg = NULL;
-               } else {
-                       /* Invalidate last entry */
-                       poll_idx[poll_fds[poll_nfds].fd].msg = NULL;
-               }
-       }
-
-       DEBUG_PTHREAD_EXIT();
-}
-
-/*
- * Called upon reception of SIGUSR2
- */
-/* ARGSUSED */
-static void
-poll_thread_sighandler(int sig)
-{
-
-       DEBUG_PTHREAD_ENTRY();
-
-       pollingevents++;
-
-       DEBUG_PTHREAD_EXIT();
-}
-
-
-
-/*
- * Public API exported functions
- */
-
-/*
- * Must be called before launching any thread.  Sets up the signal mask and
- * launches the dedicated poll slave thread.  Important note: this system
- * clobbers the SIGUSR2 signal, which the application can no longer use for
- * other purposes.  The only solution to wake the thread manager thread from
- * poll(2) is either to trigger an event through a dedicated filedescriptor,
- * or to send a signal to the process which only the polling thread allows.
- */
-int
-pthread_poll_init(void)
-{
-       int             error;
-       sigset_t        set;
-       pthread_attr_t  attr;
-       pthread_t       thread;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if (pthread_poll_initialized) {
-               error = 0;
-               goto err;
-       }
-
-       /*
-        * First block SIGUSR2 signal in the parent.  The reason why this must
-        * be called before the application launches any thread is that
-        * threads inherit the sigmask of their parent, and that all threads,
-        * but the polling thread, must block the signal.  This ensures that
-        * only the wanted thread wakes up when a SIGUSR2 signal is received.
-        * This way, we can interrupt the polling thread in poll(2), for
-        * instance, and cause it to reiterate its main loop.
-        */
-       (void) sigemptyset(&set);
-       (void) sigaddset(&set, SIGUSR2);
-       if ((error = pthread_sigmask(SIG_BLOCK, &set, NULL)) != 0)
-               goto err;
-
-       /*
-        * We'll use this pthread_ring_t to get notification from child that
-        * it is ready to process requests before proceeding.
-        */
-       if ((error = pthread_ring_init(&pthread_poll_thread_started_ring))
-           != 0)
-               goto err;
-
-       /*
-        * We may now launch the poll thread and wait for notification from it
-        * that it is ready to serve requests.  We won't need to exit this
-        * thread, so it can be launched in detached state.
-        */
-       if ((error = pthread_attr_init(&attr)) != 0)
-               goto err;
-       if ((error = pthread_attr_setdetachstate(&attr, TRUE)) != 0)
-               goto err;
-       if ((error = pthread_create(&thread, &attr, poll_thread, NULL)) != 0)
-               goto err;
-
-       /*
-        * Wait until thread is ready to serve requests
-        */
-       (void) pthread_ring_wait(&pthread_poll_thread_started_ring, NULL);
-
-       pthread_poll_initialized = TRUE;
-
-       return 0;
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * poll(2) replacement which can also be awakened by a notification happening
- * on the specified ring.  This for instance allows to process thread messages
- * as well as descriptor events.  Like poll(2), returns the number of
- * descriptors with events on success (can be 0), or returns -1 with the
- * specified error set in errno.  Unlike poll, the error ETIMEDOUT will occur
- * if the timeout expires before an event existed, or ECANCELLED if a ring
- * notification event occurred instead of a filedescriptor one.  Can also
- * return errors such as EINVAL.
- * XXX Check for ETIMEDOUT!  We probably don't do this yet.  Also, we could
- * return 0 in this case like poll(2).
- */
-int
-pthread_poll_ring(struct pollfd *fds, nfds_t nfds, int timeout,
-    pthread_ring_t *ring)
-{
-       int                     error;
-       struct poll_data        *data;
-       pthread_ring_t          *oring;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if (!pthread_poll_initialized) {
-               error = EINVAL;
-               goto err;
-       }
-
-       /*
-        * Implicit process and thread specific initializations
-        */
-       if ((error =  pthread_once(&pthread_poll_proc_initialized,
-           pthread_poll_proc_init2)) != 0)
-               goto err;
-       /*
-        * XXX Use a mutex or pthread_once() equivalent here too?
-        */
-       if ((data = pthread_getspecific(pthread_poll_proc_key)) == NULL) {
-               if ((error = pthread_poll_thread_init(&data)) != 0)
-                       goto err;
-       }
-
-       /*
-        * Perform some sanity checking on supplied arguments
-        */
-       if (fds == NULL || nfds < 1 || ring == NULL || ring->magic !=
-           PRING_MAGIC) {
-               error = EINVAL;
-               goto err;
-       }
-
-       /*
-        * Ensure that our message port's ring uses the same ring which
-        * the user supplies us.  If we didn't do this we would need to
-        * be able to wait for events on more than one ring simultaneously.
-        * Because we don't have a ring multiplexer object yet (which would
-        * be needed since a ring maps to a conditional variable among other
-        * things), we need to do process this way.
-        * XXX Could there be a race condition here?  It needs to be stressed.
-        */
-       {
-               int     mevent;
-
-               mevent = (data->port.ring != NULL ?
-                   data->port.ring->mevent : 0);
-               oring = data->port.ring;
-               (void) pthread_port_set_ring(&data->port, ring);
-               data->port.ring->mevent = mevent;
-       }
-
-       /*
-        * Send query to polling thread.  It is safe to simply reuse our
-        * message since we then expect a reply back and synchronize it.
-        */
-       data->msg.cancel = FALSE;
-       data->msg.fds = fds;
-       data->msg.nfds = nfds;
-       data->msg.timeout = timeout;
-       if ((error = pthread_msg_put(&pthread_poll_thread_port,
-           &data->msg.msgnode)) != 0)
-               goto err;
-
-       /*
-        * Interrupt polling thread which may still be waiting in poll(2).
-        * We do this by sending SIGUSR2 to the process, which only the
-        * polling thread is not blocking.  This causes the thread to reiterate
-        * its main loop, thus processing this message and going back to
-        * sleep in poll(2).
-        */
-       POLLWAKE();
-
-       /*
-        * Wait until en event occurs and notifies our ring.  An event could
-        * either be triggered by the poll request ending or by another
-        * interrupting event on the supplied ring.  If a message is queued
-        * on the port between pthread_port_set_ring() and
-        * pthread_ring_wait(), the latter immediately returns.
-        */
-       if ((error = pthread_ring_wait(ring, NULL)) != 0)
-               goto err;
-       if (pthread_msg_get(&data->port) == NULL) {
-               /*
-                * No message replied back from poll thread yet, this means
-                * that our ring was notified by another event.  Cancel request
-                * by sending event back with the cancel flag, and wait for
-                * reply message to occur (which will be the original request
-                * results we were waiting for).  error field will be set to
-                * ECANCELED by the poll thread.
-                */
-               data->msg.cancel = TRUE;
-               (void) pthread_msg_put(&pthread_poll_thread_port,
-                   &data->msg.msgnode);
-               POLLWAKE();
-               while (pthread_msg_get(&data->port) == NULL)
-                       (void) pthread_ring_wait(ring, NULL);
-       }
-       /* Unclobber user supplied ring from our port events */
-       (void) pthread_port_set_ring(&data->port, oring);
-
-       /*
-        * Error, return error number.
-        */
-       if (data->msg.error != 0) {
-               error = data->msg.error;
-               goto err;
-       }
-
-       /*
-        * Success, return number of descriptors with detected events.
-        */
-       DEBUG_PTHREAD_EXIT();
-       return data->msg.ready;
-
-err:
-       errno = error;
-
-       DEBUG_PTHREAD_EXIT();
-       return -1;
-}
-
-/*
- * accept(2) replacement which can both observe a timeout and be interrupted
- * via pthread_ring_t events.  Internally implemented using
- * pthread_poll_ring().  Will internally set the descriptor in non-blocking
- * mode if necessary, then reverting it to the mode it was supplied in.
- * Returns a new descriptor on success, or -1 on error, in which case errno
- * is set.  errno can then be EINVAL, ETIMEDOUT, ECANCELED, or others.
- * Timeout is in milliseconds, like for poll(2) and can be -1.
- */
-int
-pthread_accept_ring(int s, struct sockaddr *addr, socklen_t *addrlen,
-    int timeout, pthread_ring_t *ring)
-{
-       int             oflags, nflags, d, error = 0;
-       struct pollfd   fd;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if (!pthread_poll_initialized) {
-               errno = EINVAL;
-               goto err;
-       }
-
-       /*
-        * First get current fcntl status flags, and set descriptor to
-        * non-blocking mode if necessary.
-        */
-       if ((oflags = nflags = fcntl(s, F_GETFL)) == -1)
-               goto err;
-       if ((oflags & O_NONBLOCK) == 0) {
-               nflags |= O_NONBLOCK;
-               if (fcntl(s, F_SETFL, nflags) == -1)
-                       goto err;
-       }
-
-       if ((d = accept(s, addr, addrlen)) == -1) {
-               if (errno != EAGAIN) /* XXX Add others? */
-                       goto end;
-       } else
-               goto end;
-
-       /*
-        * EAGAIN, poll until completion, timeout or ring event.
-        */
-       fd.fd = d;
-       fd.events = POLLIN;
-       if ((error = pthread_poll_ring(&fd, 1, timeout, ring)) == 1 &&
-           (fd.revents & POLLIN) != 0)
-               error = 0;
-       else
-               error = errno;
-
-end:
-       /*
-        * Restore supplied descriptor fcntl status flags if necessary
-        */
-       if (nflags != oflags)
-               (void) fcntl(s, F_SETFL, oflags);
-
-       if (error != 0) {
-               if (d != -1) {
-                       (void) close(d);
-                       d = -1;
-               }
-               errno = error;
-               goto err;
-       }
-
-       DEBUG_PTHREAD_EXIT();
-       return d;
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return -1;
-}
-
-/*
- * connect(2) replacement which can both observe a timeout and be interrupted
- * via pthread_ring_t events.  Internally implemented using
- * pthread_poll_ring().  Will internally set the descriptor in non-blocking
- * mode if necessary, then reverting it back to the mode it was supplied in.
- * Returns 0 on success, or -1, in which case errno is set.  errno can be
- * EINVAL, ETIMEDOUT, ECANCELED or others.
- * Timeout is in milliseconds, like for poll(2) and can be -1.
- * For the application to know the actual connection status result, it should
- * poll until completion and verify the status using getsockopt(2) with
- * SOL_SOCKET level and SO_ERROR option.  It can alternatively continue to call
- * this function in a loop until completion.  Calling the function on an
- * already connected socket will result in EISCONN.
- */
-int
-pthread_connect_ring(int s, const struct sockaddr *name, socklen_t namelen,
-    int timeout, pthread_ring_t *ring)
-{
-       int             oflags, nflags, error = 0;
-       struct pollfd   fd;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if (!pthread_poll_initialized) {
-               errno = EINVAL;
-               goto err;
-       }
-
-       /*
-        * First get current fcntl status flags, and set descriptor to
-        * non-blocking mode if necessary.
-        */
-       if ((oflags = nflags = fcntl(s, F_GETFL)) == -1)
-               goto err;
-       if ((oflags & O_NONBLOCK) == 0) {
-               nflags |= O_NONBLOCK;
-               if (fcntl(s, F_SETFL, nflags) == -1)
-                       goto err;
-       }
-
-       if ((error = connect(s, name, namelen)) == -1) {
-               if (errno != EINPROGRESS && errno != EALREADY) {
-                       error = errno;
-                       goto end;
-               }
-       } else
-               goto end;
-
-       /*
-        * EINPROGRESS or EALREADY, poll until completion, timeout or ring
-        * event.
-        */
-       fd.fd = s;
-       fd.events = POLLOUT;
-       if (pthread_poll_ring(&fd, 1, timeout, ring) == 1 &&
-           (fd.revents & POLLOUT) != 0) {
-               socklen_t       l;
-
-               /*
-                * connect(2) completed, return result
-                */
-               if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &l) == -1)
-                       error = errno;
-       }
-
-end:
-       /*
-        * Restore supplied descriptor fcntl status flags if necessary
-        */
-       if (nflags != oflags)
-               (void) fcntl(s, F_SETFL, oflags);
-
-       if (error != 0) {
-               errno = error;
-               goto err;
-       }
-
-       DEBUG_PTHREAD_EXIT();
-       return 0;
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return -1;
-}
diff --git a/tests/pthread_utils/mm_pthread_poll.h b/tests/pthread_utils/mm_pthread_poll.h
deleted file mode 100644 (file)
index 77af18a..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* $Id: mm_pthread_poll.h,v 1.6 2005/11/22 18:03:48 mmondor Exp $ */
-
-/*
- * Copyright (C) 2005, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef MM_PTHREAD_POLL_H
-#define MM_PTHREAD_POLL_H
-
-
-
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <fcntl.h>
-#include <poll.h>
-
-#include <mm_pthread_msg.h>
-
-
-
-extern int     pthread_poll_init(void);
-extern int     pthread_poll_ring(struct pollfd *, nfds_t, int,
-                   pthread_ring_t *);
-extern int     pthread_accept_ring(int, struct sockaddr *, socklen_t *, int,
-                   pthread_ring_t *);
-extern int     pthread_connect_ring(int, const struct sockaddr *, socklen_t,
-                   int, pthread_ring_t *);
-
-
-
-#endif
diff --git a/tests/pthread_utils/mm_pthread_pool.c b/tests/pthread_utils/mm_pthread_pool.c
deleted file mode 100644 (file)
index 80ba5fb..0000000
+++ /dev/null
@@ -1,504 +0,0 @@
-/* $Id: mm_pthread_pool.c,v 1.7 2006/02/05 13:00:48 mmondor Exp $ */
-
-/*
- * Copyright (C) 2004-2005, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Implementation of a pool of ready threads which adapts with concurrency
- * needs.  These ready threads can serve requests passed through efficient
- * inter-thread messaging.  mmpool(3) is used for the pool functionality.
- */
-
-
-
-#include <pthread.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include <mm_pthread_debug.h>
-#include <mm_pthread_pool.h>
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2004-2005\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mm_pthread_pool.c,v 1.7 2006/02/05 13:00:48 mmondor Exp $");
-
-
-
-/*
- * STATIC FUNCTIONS PROTOTYPES
- */
-
-inline static pthread_object_t *thread_object_alloc(void);
-inline static void             thread_object_free(pthread_object_t *);
-static bool                    thread_object_constructor(pnode_t *);
-static void                    thread_object_destructor(pnode_t *);
-static void                    *thread_object_main(void *);
-
-
-
-/*
- * GLOBALS
- */
-
-static bool                    thread_object_initialized = FALSE;
-static pthread_attr_t          thread_object_attr;
-static pool_t                  thread_object_pool;
-static pool_t                  thread_object_msg_pool;
-static pthread_mutex_t         thread_object_pool_mutex =
-                                   PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t         thread_object_msg_pool_mutex =
-                                   PTHREAD_MUTEX_INITIALIZER;
-static pthread_ring_t          thread_started_ring;
-
-
-
-/*
- * EXPORTED PUBLIC FUNCTIONS
- */
-
-/*
- * Must be called to initialize the pthreads pool subsystem, before calling
- * any other function of this API.  Returns 0 on success, or an error number.
- * <initial> threads are launched, and more will be launched in increments
- * of <initial> whenever necessary.  These will also only be destroyed in
- * decrements of <initial> whenever that many threads have not been in use for
- * some time, and a minimum of <initial> threads will always be kept.
- * Setting <initial> to high values may actually degrade performance with some
- * unefficient threading implementations.  It is not recommended to use more
- * than 8 using the pth(3) library.  Using NetBSD 2.0+ SA threads, a high
- * number does not reduce performance.  We current do not observe any limit
- * whatsoever according to the number of threads launched over time.  It is the
- * application's responsibility to ensure to observe decent concurrency limits
- * before calling pthread_object_call().
- */
-int
-pthread_object_init(int initial)
-{
-       int     error = 0;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if (thread_object_initialized) {
-               error = EINVAL;
-               goto err;
-       }
-
-       /*
-        * Create attributes which will be used for threads of the pool.
-        * We want them to be joinable.
-        */
-       if ((error = pthread_attr_init(&thread_object_attr)) != 0)
-               goto err;
-       if ((error = pthread_attr_setdetachstate(&thread_object_attr, 0))
-           != 0)
-               goto err;
-
-       /*
-        * We use this ring to obtain notification of ready children when
-        * launching them.  This is required for proper synchronization to
-        * avoid aweful race conditions.
-        */
-       if ((error = pthread_ring_init(&thread_started_ring)) != 0)
-               goto err;
-
-       /*
-        * First initialize the message subsystem pool
-        */
-       if (!pool_init(&thread_object_msg_pool, "thread_object_msg_pool",
-           malloc, free, NULL, NULL, sizeof(pthread_object_msg_t),
-           32768 / sizeof(pthread_object_msg_t), 1, 0)) {
-               error = ENOMEM;
-               goto err;
-       }
-
-       /*
-        * Now initialize the threads pool.  This creates threads, uses
-        * synchronization with thread_started_ring, and uses the message
-        * subsystem, which all must be initialized and ready.
-        */
-       if (!pool_init(&thread_object_pool, "thread_object_pool",
-           malloc, free, thread_object_constructor, thread_object_destructor,
-           sizeof(pthread_object_t), initial, 1, 0)) {
-               error = ENOMEM;
-               goto err;
-       }
-
-       thread_object_initialized = TRUE;
-
-       DEBUG_PTHREAD_EXIT();
-       return 0;
-
-err:
-       if (POOL_VALID(&thread_object_msg_pool))
-               pool_destroy(&thread_object_msg_pool);
-       if (POOL_VALID(&thread_object_pool))
-               pool_destroy(&thread_object_pool);
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Allows allocation/creation of a message suitable for asynchronous requests
- * with the threads via their main message port provided by this system.
- * Returns new message, or NULL on error.
- */
-inline pthread_object_msg_t *
-pthread_object_msg_alloc(void)
-{
-       pthread_object_msg_t    *msg = NULL;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if (pthread_mutex_lock(&thread_object_msg_pool_mutex) != 0)
-               goto err;
-       msg = (pthread_object_msg_t *)pool_alloc(&thread_object_msg_pool,
-           FALSE);
-       (void) pthread_mutex_unlock(&thread_object_msg_pool_mutex);
-
-       (void) pthread_msg_init(&msg->message, NULL);
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return msg;
-}
-
-/*
- * Permits to free/destroy a message which was allocated using
- * pthread_object_msg_alloc() and sent asynchroneously.
- */
-inline int
-pthread_object_msg_free(pthread_object_msg_t *msg)
-{
-       int     error = 0;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       (void) pthread_msg_destroy(&msg->message);
-
-       if ((error = pthread_mutex_lock(&thread_object_msg_pool_mutex)) != 0)
-               goto err;
-       (void) pool_free((pnode_t *)msg);
-       (void) pthread_mutex_unlock(&thread_object_msg_pool_mutex);
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Allows to invoke a thread of the pool to perform execution of the wanted
- * function.  This is very efficient since the threads are already created and
- * are waiting for requests.  There is no maximum concurrency limit enforced by
- * this system; It is the responsibility of the application to restrict
- * concurrency as necessary by keeping internal information on the current
- * number of requests.  0 is returned on success, or an error number.
- * XXX Add support for synchroneous and asynchroneous operation.  Current
- * operation is only asynchroneous, but we would like to add a boolean here to
- * decide.  We also could add back the result value of the thread function
- * which would only be useful in synchroneous operation, when we are waiting
- * until the task ends...  Of course, it's still easy for applications to use
- * these in a synchroneous manner, by using a message and/or ring,
- * conditionnal variable, etc.
- * Also evaluate if a callback function to be called to notify end of
- * asynchroneous operation would be useful.
- */
-int
-pthread_object_call(pthread_port_t **port,
-    void (*function)(pthread_object_t *, void *), void *args)
-{
-       pthread_object_t        *obj = NULL;
-       pthread_object_msg_t    *msg = NULL;
-       int                     error;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if (function == NULL) {
-               error = EINVAL;
-               goto err;
-       }
-
-       /*
-        * Allocate a thread from the pool to reserve it, and tell it to call
-        * a function via a message.  The message cannot be on the stack in
-        * this case, since it holds arguments to be passed to a thread, and
-        * also consists of an asynchroneous message for wich we do not expect
-        * a response back, waiting for it.  We just dispatch it and go on.
-        */
-       if ((obj = thread_object_alloc()) == NULL) {
-               error = ENOMEM;
-               goto err;
-       }
-       if ((msg = pthread_object_msg_alloc()) == NULL) {
-               error = ENOMEM;
-               goto err;
-       }
-
-       msg->command = PTHREAD_OBJ_CALL;
-       msg->u.call.function = function;
-       msg->u.call.arguments = args;
-       if ((error = pthread_msg_put(obj->port, &msg->message)) != 0)
-               goto err;
-
-       /*
-        * Everything successful;
-        * If caller wants the message port of the thread, supply it
-        */
-       if (port != NULL)
-               *port = obj->port;
-
-       DEBUG_PTHREAD_EXIT();
-       return 0;
-
-err:
-       if (msg != NULL)
-               pthread_object_msg_free(msg);
-       if (obj != NULL)
-               thread_object_free(obj);
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-
-
-/*
- * INTERNAL STATIC FUNCTIONS
- */
-
-/*
- * Internally used to allocate a ready thread from the pool.
- */
-inline static pthread_object_t *
-thread_object_alloc(void)
-{
-       pthread_object_t        *obj = NULL;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if (pthread_mutex_lock(&thread_object_pool_mutex) != 0)
-               goto err;
-       obj = (pthread_object_t *)pool_alloc(&thread_object_pool, FALSE);
-       (void) pthread_mutex_unlock(&thread_object_pool_mutex);
-
-err:
-       return obj;
-}
-
-/*
- * Internally used to free a no longer needed thread back to the pool of ready
- * threads.
- */
-inline static void
-thread_object_free(pthread_object_t *obj)
-{
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if (pthread_mutex_lock(&thread_object_pool_mutex) == 0) {
-               (void) pool_free((pnode_t *)obj);
-               (void) pthread_mutex_unlock(&thread_object_pool_mutex);
-       }
-
-       DEBUG_PTHREAD_EXIT();
-}
-
-/*
- * Internally called by mmpool(3) to create a thread object.
- */
-static bool
-thread_object_constructor(pnode_t *pnode)
-{
-       pthread_object_t        *obj = (pthread_object_t *)pnode;
-       int                     success = TRUE;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       /*
-        * Note that we leave thread_object_main() initialize the port field
-        * when it creates its port and ring.
-        */
-       if (pthread_create(&obj->thread, &thread_object_attr,
-           thread_object_main, obj) != 0) {
-               success = FALSE;
-               goto err;
-       }
-
-       /*
-        * Wait until new thread ready notification.  Without this, at least
-        * with NetBSD 2.0 SA threads, hell would break loose.  Thread creation
-        * isn't really a bottleneck in our case anyways, since we only need
-        * to do it when all threads of the pool are already busy.
-        */
-       (void) pthread_ring_wait(&thread_started_ring, NULL);
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return success;
-}
-
-/*
- * Internally called by mmpool(3) to destroy a thread object.
- */
-static void
-thread_object_destructor(pnode_t *pnode)
-{
-       pthread_object_t        *obj = (pthread_object_t *)pnode;
-       pthread_object_msg_t    *msg;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       /*
-        * To be freed, the thread has to be terminated.  We thus send it a
-        * quit message and then wait for it to exit using pthread_join().
-        * Note that we let the thread destroy the port field.  Although we
-        * theoretically could use a message on the stack here, let's be safe.
-        * Thread destruction is only performed rarely anyways, so this isn't
-        * a performance problem.
-        */
-       if ((msg = pthread_object_msg_alloc()) != NULL) {
-               msg->command = PTHREAD_OBJ_QUIT;
-               (void) pthread_msg_put(obj->port, &msg->message);
-       }
-       (void) pthread_join(obj->thread, NULL);
-
-       DEBUG_PTHREAD_EXIT();
-}
-
-/*
- * Actual thread's main loop.  We create a message port and listen for command
- * messages (quit and call).  When we obtain a quit request, we destroy the
- * port and exit cleanly.  The quit event can never occur during the execution
- * of a call command, since it is only called on already freed thread nodes
- * (by mmpool(3) pool_free()).  It is advized to applications which need to
- * obtain and use the port of the thread after thread_object_call() to only
- * send proper user messages, not system reserved ones.
- */
-static void *
-thread_object_main(void *args)
-{
-       pthread_object_t        *obj = (pthread_object_t *)args;
-       pthread_port_t          port;
-       pthread_ring_t          ring;
-       pthread_msg_t           *imsg;
-       pthread_object_msg_t    *msg;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       /*
-        * Create our incomming message port as well as its corresponding
-        * notification ring we can sleep on.  Then advertize our port address.
-        * Ideally, we should somehow panic if any of this initialization
-        * fails. XXX
-        */
-       (void) pthread_port_init(&port);
-       (void) pthread_ring_init(&ring);
-       (void) pthread_port_set_ring(&port, &ring);
-       obj->port = &port;
-
-       /*
-        * Notify parent that we are ready, so that it may proceed
-        */
-       (void) pthread_ring_notify(&thread_started_ring);
-
-       /*
-        * Main loop, which keeps executing until we obtain a PTHREAD_OBJ_QUIT
-        * message, at which event we cleanly exit.
-        */
-       for (;;) {
-               /*
-                * Wait for any message(s) to be available, without taking any
-                * CPU time.
-                */
-               (void) pthread_ring_wait(&ring, NULL);
-
-               /*
-                * We were awaken because at least one message is available.
-                * Process all messages in the queue.
-                */
-               while ((imsg = pthread_msg_get(&port)) != NULL) {
-                       msg = (pthread_object_msg_t *)(&((pnode_t *)imsg)[-1]);
-                       if (msg->command == PTHREAD_OBJ_QUIT) {
-                               /*
-                                * We are ordered to exit by the object
-                                * destructor.
-                                */
-                               pthread_object_msg_free(msg);
-                               goto end;
-                       }
-                       if (msg->command == PTHREAD_OBJ_CALL) {
-                               /*
-                                * Request to execute a function.  This means
-                                * that we were allocated/reserved first.
-                                */
-                               msg->u.call.function(obj,
-                                   msg->u.call.arguments);
-                               pthread_object_msg_free(msg);
-                               /*
-                                * Free/release us back, so that we be
-                                * available again to process further
-                                * requests.  It is possible that freeing
-                                * ourselves cause a PTHREAD_OBJ_QUIT message
-                                * to be queued soon on our port by the
-                                * destructor function.  This is safe, since
-                                * the destructor does not cause us to be
-                                * destroyed until it waits for us to have
-                                * ended cleanly using pthread_join().
-                                */
-                               thread_object_free(obj);
-                       }
-               }
-       }
-
-end:
-       /*
-        * Discard messages that are still queued on our port (if any)
-        */
-       while ((imsg = pthread_msg_get(&port)) != NULL) {
-               msg = (pthread_object_msg_t *)(&((pnode_t *)imsg)[-1]);
-               pthread_object_msg_free(msg);
-       }
-       /*
-        * Free our resources and exit.
-        */
-       (void) pthread_port_destroy(&port);
-       (void) pthread_ring_destroy(&ring);
-
-       DEBUG_PTHREAD_EXIT();
-       pthread_exit(NULL);
-
-       /* NOTREACHED */
-       return NULL;
-}
diff --git a/tests/pthread_utils/mm_pthread_pool.h b/tests/pthread_utils/mm_pthread_pool.h
deleted file mode 100644 (file)
index 2a46ebd..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/* $Id: mm_pthread_pool.h,v 1.1 2004/12/27 11:16:16 mmondor Exp $ */
-
-/*
- * Copyright (C) 2004-2005, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef MM_PTHREAD_POOL_H
-#define MM_PTHREAD_POOL_H
-
-
-
-#include <pthread.h>
-
-#include <mmtypes.h>
-#include <mmpool.h>
-
-#include <mm_pthread_msg.h>
-
-
-
-typedef struct {
-       pnode_t         node;
-       pthread_t       thread;
-       pthread_port_t  *port;
-} pthread_object_t;
-
-typedef struct {
-       pnode_t         node;
-       pthread_msg_t   message;
-       int             command;
-       union {
-               /* PTHREAD_OBJ_CALL, sent to thread_object_main() */
-               struct {
-                       void    (*function)(pthread_object_t *, void *);
-                       void    *arguments;
-               } call;
-               /* PTHREAD_OBJ_QUIT, sent to thread_oject_reaper() */
-               pthread_object_t *quit;
-               /* PTHREAD_OBJ_USER, custom user messages */
-               struct {
-                       int     user_command;
-                       void    *user_data;
-               } user;
-       } u;
-} pthread_object_msg_t;
-
-enum pthread_object_commands {
-       PTHREAD_OBJ_CALL,
-       PTHREAD_OBJ_QUIT,
-       PTHREAD_OBJ_USER,
-       PTHREAD_OBJ_MAX
-};
-
-
-
-extern int                             pthread_object_init(int);
-extern inline pthread_object_msg_t     *pthread_object_msg_alloc(void);
-extern inline int                      pthread_object_msg_free(
-                                           pthread_object_msg_t *);
-extern int                             pthread_object_call(pthread_port_t **,
-                                           void (*)(pthread_object_t *,
-                                           void *), void *);
-
-
-
-#endif
diff --git a/tests/pthread_utils/mm_pthread_sleep.c b/tests/pthread_utils/mm_pthread_sleep.c
deleted file mode 100644 (file)
index a9f8c58..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/* $Id: mm_pthread_sleep.c,v 1.5 2006/02/05 13:00:48 mmondor Exp $ */
-
-/*
- * Copyright (C) 2005, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <pthread.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <mm_pthread_debug.h>
-#include <mm_pthread_msg.h>
-#include <mm_pthread_sleep.h>
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2005\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mm_pthread_sleep.c,v 1.5 2006/02/05 13:00:48 mmondor Exp $");
-
-
-
-static int             pthread_sleep_proc_init(void);
-static void            pthread_sleep_proc_init2(void);
-static int             pthread_sleep_thread_init(pthread_ring_t **);
-static void            pthread_sleep_thread_exit(void *);
-
-static pthread_key_t   pthread_sleep_proc_key;
-static pthread_once_t  pthread_sleep_proc_initialized = PTHREAD_ONCE_INIT;
-
-
-
-static int
-pthread_sleep_proc_init(void)
-{
-       int     error;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       error = pthread_key_create(&pthread_sleep_proc_key,
-           pthread_sleep_thread_exit);
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-static void
-pthread_sleep_proc_init2(void)
-{
-       int     error;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if ((error = pthread_sleep_proc_init()) != 0) {
-               (void) fprintf(stderr, "pthread_sleep_proc_init() - %s\n",
-                   strerror(error));
-               DEBUG_PTHREAD_EXIT();
-               exit(EXIT_FAILURE);
-       }
-
-       DEBUG_PTHREAD_EXIT();
-}
-
-static int
-pthread_sleep_thread_init(pthread_ring_t **res)
-{
-       int             error;
-       pthread_ring_t  *ring;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       if ((ring = malloc(sizeof(pthread_ring_t))) == NULL) {
-               error = ENOMEM;
-               goto err;
-       }
-
-       if ((error = pthread_ring_init(ring)) != 0)
-               goto err;
-
-       if ((error = pthread_setspecific(pthread_sleep_proc_key, ring)) != 0)
-               goto err;
-
-       *res = ring;
-
-       DEBUG_PTHREAD_EXIT();
-       return 0;
-
-err:
-       if (ring != NULL)
-               free(ring);
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-static void
-pthread_sleep_thread_exit(void *specific)
-{
-       pthread_ring_t  *ring = (pthread_ring_t *)specific;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       (void) pthread_ring_destroy(ring);
-       free(ring);
-
-       /*
-        * Although NetBSD threads don't need this, some pthread
-        * implementations do.  Some will crash for attempting to reference the
-        * already freed memory twice calling us again until we NULL the
-        * pointer for the data.  Lame, but the POSIX standard was unclear
-        * about this.
-        */
-       (void) pthread_setspecific(pthread_sleep_proc_key, NULL);
-
-       DEBUG_PTHREAD_EXIT();
-}
-
-
-
-/*
- * Suspends the calling thread for duration specified in supplied timespec.
- * Returns 0 on success, or an error number.
- */
-int
-pthread_nanosleep(struct timespec *ts)
-{
-       int             error;
-       struct timeval  tv;
-       struct timespec its;
-       pthread_ring_t  *ring;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       /*
-        * Process specific initialization if needed
-        */
-       if ((error = pthread_once(&pthread_sleep_proc_initialized,
-           pthread_sleep_proc_init2)) != 0)
-               goto err;
-       /*
-        * Thread specific initialization if needed
-        * XXX Use pthread_once() here too, or mutex around ring?
-        */
-       if ((ring = pthread_getspecific(pthread_sleep_proc_key)) == NULL) {
-               if ((error = pthread_sleep_thread_init(&ring)) != 0)
-                       goto err;
-       }
-
-       /*
-        * Generate absolute time timespec using current time and supplied
-        * timespec delay.
-        */
-       if (gettimeofday(&tv, NULL) == -1) {
-               error = errno;
-               goto err;
-       }
-       TIMEVAL_TO_TIMESPEC(&tv, &its);
-       timespecadd(&its, ts, &its);
-
-       /*
-        * We can finally sleep.  We expect ETIMEDOUT to be the normal return
-        * value in this case, which we convert to a no-error.  Other errors
-        * will be returned un changed.
-        */
-       if ((error = pthread_ring_wait(ring, &its)) == ETIMEDOUT)
-               error = 0;
-
-err:
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Suspends the current thread for the duration specified into supplied
- * timeval.  Returns 0 on success or an error number.
- */
-int
-pthread_microsleep(struct timeval *tv)
-{
-       struct timespec ts;
-       int             error;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       TIMEVAL_TO_TIMESPEC(tv, &ts);
-       error = pthread_nanosleep(&ts);
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Suspends execution of current thread for duration of specified
- * milliseconds.  Returns 0 on success or an error number.
- */
-int
-pthread_millisleep(unsigned int ms)
-{
-       struct timeval  tv;
-       int             error;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       tv.tv_sec = ms / 1000;
-       tv.tv_usec = (ms % 1000) * 1000;
-       error = pthread_microsleep(&tv);
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Suspends execution of thread for duration of specified number of seconds.
- * Returns 0 on success or an error number.
- */
-unsigned int
-pthread_sleep(unsigned int seconds)
-{
-       struct timespec ts;
-       int             error;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       ts.tv_sec = seconds;
-       ts.tv_nsec = 0;
-       error = pthread_nanosleep(&ts);
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
-
-/*
- * Suspends execution of thread for durection of specified number of
- * microseconds.  Like usleep(3).
- */
-int
-pthread_usleep(useconds_t ms)
-{
-       struct timeval  tv;
-       int             error;
-
-       DEBUG_PTHREAD_ENTRY();
-
-       tv.tv_sec = 0;
-       tv.tv_usec = ms;
-       error = pthread_microsleep(&tv);
-
-       DEBUG_PTHREAD_EXIT();
-       return error;
-}
diff --git a/tests/pthread_utils/mm_pthread_sleep.h b/tests/pthread_utils/mm_pthread_sleep.h
deleted file mode 100644 (file)
index 93b6766..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* $Id: mm_pthread_sleep.h,v 1.2 2005/09/16 08:49:06 mmondor Exp $ */
-
-/*
- * Copyright (C) 2005, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef MM_PTHREAD_SLEEP_H
-#define MM_PTHREAD_SLEEP_H
-
-
-
-#include <sys/time.h>
-#include <pthread.h>
-#include <unistd.h>
-
-
-
-extern int             pthread_nanosleep(struct timespec *);
-extern int             pthread_microsleep(struct timeval *);
-extern int             pthread_millisleep(unsigned int);
-extern unsigned int    pthread_sleep(unsigned int);
-extern int             pthread_usleep(useconds_t);
-
-
-
-#endif
diff --git a/tests/pthread_utils/tests/msg_test.c b/tests/pthread_utils/tests/msg_test.c
deleted file mode 100644 (file)
index bb7e918..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/* $Id: msg_test.c,v 1.3 2005/11/18 10:54:58 mmondor Exp $ */
-
-/*
- * Copyright (C) 2005, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-
-#include <mm_pthread_msg.h>
-#include <mm_pthread_pool.h>
-#include <mm_pthread_poll.h>
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2005\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: msg_test.c,v 1.3 2005/11/18 10:54:58 mmondor Exp $");
-
-
-
-#define        THREADS                 32
-#define ROUNDS                 8
-#define TIMEOUT                        1
-/*#define PRINTLOCK*/
-/*#define NOPRINT*/
-
-
-
-struct message {
-       pthread_msg_t   node;
-       int             id, i;
-};
-
-
-
-int            main(void);
-static void    threadfunc(pthread_object_t *, void *);
-static void    printfunc(const char *, ...);
-
-
-
-static pthread_port_t  main_port;
-static pthread_mutex_t print_lock;
-
-
-
-int
-main(void)
-{
-       pthread_ring_t  ring;
-       struct message  *msg;
-       int             i, err;
-       int             threads_args[THREADS];
-       struct timeval  tv;
-       struct timespec ts, ts1;
-
-       if ((err = pthread_mutex_init(&print_lock, NULL)) != 0) {
-               (void) printf("main() - stdout lock - %s\n", strerror(err));
-               exit(EXIT_FAILURE);
-       }
-
-       if ((err = pthread_port_init(&main_port)) != 0 ||
-           (err = pthread_ring_init(&ring)) != 0 ||
-           (err = pthread_port_set_ring(&main_port, &ring)) != 0) {
-               printfunc("main() - initialization - %s\n", strerror(err));
-               exit(EXIT_FAILURE);
-       }
-
-       printfunc("Main: launching threads\n");
-
-       if ((err = pthread_poll_init()) != 0) {
-               printfunc("main() - pthread_poll_init() - %s\n",
-                   strerror(err));
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * Initializes a poll of ready threads which can be dispatched
-        * functions to execute.
-        */
-       if ((err = pthread_object_init(THREADS + 1)) != 0) {
-               printfunc("main() - pthread_object_init() - %s\n",
-                   strerror(err));
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * Now dispatch a main reentrant function to many threads, without
-        * waiting for them to complete, in an asynchroneous manner.
-        * XXX Because of the way this works, the parent main thread should
-        * actually already be listening to messages...  We did create a port
-        * however, which should queue messages until we reach the main loop.
-        */
-       for (i = 0; i < THREADS; i++) {
-               threads_args[i] = i;
-               if ((err = pthread_object_call(NULL, threadfunc,
-                   &threads_args[i])) != 0)
-                       printfunc("main() - pthread_object_call() - %s\n",
-                           strerror(errno));
-       }
-
-       ts1.tv_sec = TIMEOUT;
-       ts1.tv_nsec = 0;
-       for (;;) {
-               /*
-                * Read messages as long as there are any, and reply to each
-                * of them in a synchroneous manner.
-                */
-               while ((msg = (struct message *)pthread_msg_get(&main_port))
-                   != NULL) {
-
-                       printfunc(
-                           "Main: Received message %d from thread #%d\n",
-                           msg->i, msg->id);
-
-                       if ((err = pthread_msg_reply((pthread_msg_t *)msg))
-                           != 0)
-                               printfunc(
-                                   "Main: pthread_message_reply() - %s\n",
-                                   strerror(err));
-               }
-
-               /*
-                * No more messages to process; Wait for any message(s) to be
-                * available.
-                * Note that there is special provision in the event where
-                * this loop first polling for new messages before processing
-                * them, which causes waiting for the ring to immediately
-                * return instead of actually waiting if any messages already
-                * have been sent.
-                */
-               printfunc("Main: Waiting for messages\n");
-
-               (void) gettimeofday(&tv, NULL);
-               TIMEVAL_TO_TIMESPEC(&tv, &ts);
-               timespecadd(&ts, &ts1, &ts);
-               if ((err = pthread_ring_wait(&ring, &ts)) != 0) {
-                       printfunc("Main: pthread_ring_wait() - %s\n",
-                           strerror(err));
-                       break;
-               }
-       }
-
-       (void) pthread_mutex_destroy(&print_lock);
-       (void) pthread_port_destroy(&main_port);
-       (void) pthread_ring_destroy(&ring);
-
-       return 0;
-}
-
-static void
-threadfunc(pthread_object_t *obj, void *args)
-{
-       int             id = *(int *)args;
-       int             i, err;
-       struct message  msg;
-       pthread_port_t  rport;
-       pthread_ring_t  rring;
-
-       if ((err = pthread_port_init(&rport)) != 0 ||
-           (err = pthread_ring_init(&rring)) != 0 ||
-           (err = pthread_port_set_ring(&rport, &rring)) != 0 ||
-           (err = pthread_msg_init((pthread_msg_t *)&msg, &rport)) != 0) {
-               printfunc("threadfunc() - initialization - %s\n",
-                   strerror(err));
-               return;
-       }
-
-       msg.id = id;
-
-       (void) printfunc("Thread #%d started\n", id);
-
-       for (i = 0; i < ROUNDS; i++) {
-               /*
-                * Prepare and send synchronous message.  For asynchronous
-                * operation, we would need to allocate a message and to send
-                * it, and not expect a reply back immediately, even letting
-                * the other end free the message as necessary.  In synchronous
-                * mode we can use the same message over and over and share
-                * its memory area using proper send/reply methods for
-                * synchronization.
-                */
-               msg.i = i;
-               if ((err = pthread_msg_put(&main_port, (pthread_msg_t *)&msg))
-                   != 0)
-                       printfunc("Thread: pthread_message_put() - %s\n",
-                           strerror(err));
-
-               /* Now wait for synchronous reply and discard it */
-               if ((err = pthread_ring_wait(&rring, NULL)) != 0) {
-                       printfunc("Thread: pthread_ring_wait() - %s\n",
-                           strerror(err));
-                       break;
-               }
-               if (pthread_msg_get(&rport) == NULL)
-                       printfunc("Thread: pthread_msg_get() == NULL!?\n");
-               printfunc("Thread #%d received reply message for %d\n",
-                   id, i);
-       }
-
-       printfunc("Thread #%d ending\n", id);
-
-       (void) pthread_port_destroy(&rport);
-       (void) pthread_ring_destroy(&rring);
-       (void) pthread_msg_destroy((pthread_msg_t *)&msg);
-}
-
-static void
-printfunc(const char *fmt, ...)
-{
-       char    buf[1024];
-       va_list arg_ptr;
-       int     len;
-
-#ifdef NOPRINT
-       return;
-#endif
-
-       *buf = '\0';
-       va_start(arg_ptr, fmt);
-       if ((len = vsnprintf(buf, 1023, fmt, arg_ptr)) < 1)
-               return;
-       va_end(arg_ptr);
-
-#ifdef PRINTLOCK
-       (void) pthread_mutex_lock(&print_lock);
-#endif
-       (void) fwrite(buf, len, 1, stdout);
-#ifdef PRINTLOCK
-       (void) fflush(stdout);
-       (void) pthread_mutex_unlock(&print_lock);
-#endif
-}
diff --git a/tests/pthread_utils/tests/poll_test.c b/tests/pthread_utils/tests/poll_test.c
deleted file mode 100644 (file)
index 7be14bc..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/* $Id: poll_test.c,v 1.1 2005/09/14 23:48:10 mmondor Exp $ */
-
-/*
- * Copyright (C) 2005, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-
-#include <mm_pthread_msg.h>
-#include <mm_pthread_pool.h>
-#include <mm_pthread_poll.h>
-
-
-
-MMCOPYRIGHT("@(#) Copyright (c) 2005\n\
-\tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: poll_test.c,v 1.1 2005/09/14 23:48:10 mmondor Exp $");
-
-
-
-int    main(void);
-
-
-
-int
-main(void)
-{
-       int     err;
-
-       if ((err = pthread_poll_init()) != 0) {
-               (void) fprintf(stderr, "main() - pthread_poll_init() - %s\n",
-                   strerror(err));
-               exit(EXIT_FAILURE);
-       }
-
-       return 0;
-}
diff --git a/tests/pthread_utils/tests/polltest.c b/tests/pthread_utils/tests/polltest.c
deleted file mode 100644 (file)
index ceedfd5..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * The goal of this program is to verify if it is valid for multiple threads
- * to poll(2) on the same filedescriptor, and if so, what happens whenever
- * an event is triggered on that descriptor.
- *
- * XXX Problems:
- * - Only one of the polling threads seems to be awaken when an event occurs
- *   on the descriptor. This probably means that using a signal would be
- *   better... I sure don't want to need a filedescriptor per ring...
- *   If I did however, would this really hurt? Are there that many rings?
- *   But oops, this actually means two filedescriptors for each!
- *   using a signal is probably better. However, we then need to clobber some
- *   signal... We could use SIGUSR2.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <pthread.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-
-
-#define THREADS        8
-
-
-
-int            main(void);
-static void    *thread_poll(void *);
-static void    *thread_notify(void *);
-static void    thread_print(int, const char *);
-
-
-
-static int             sockets[2];
-static int             threadargs[THREADS];
-static pthread_mutex_t print_mutex;
-static pthread_mutex_t sockets_mutex;
-
-
-
-int
-main(void)
-{
-       pthread_t       threadid;
-       int             i;
-
-       /*
-        * Create socketpair which will be used to trigger events to awaken
-        * polling threads.
-        */
-       if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, sockets) != 0) {
-               perror("socketpair()");
-               exit(EXIT_FAILURE);
-       }
-       if (fcntl(sockets[0], F_SETFL, O_NONBLOCK) != 0 ||
-           fcntl(sockets[1], F_SETFL, O_NONBLOCK) != 0) {
-               perror("fcntl()");
-               exit(EXIT_FAILURE);
-       }
-
-       pthread_mutex_init(&print_mutex, NULL);
-       pthread_mutex_init(&sockets_mutex, NULL);
-
-       /*
-        * First launch THREADS polling threads
-        */
-       for (i = 0; i < THREADS; i++) {
-               threadargs[i] = i;
-               pthread_create(&threadid, NULL, thread_poll, &threadargs[i]);
-       }
-       sleep(1);
-
-       /*
-        * And finally launch notifyer thread
-        */
-       pthread_create(&threadid, NULL, thread_notify, NULL);
-
-       /*
-        * Now just wait
-        */
-       for (;;)
-               (void) pause();
-}
-
-static void *
-thread_poll(void *args)
-{
-       struct pollfd   fds[1];
-       int             n;
-       int             id = *(int *)args;
-       char            c;
-
-       fds[0].fd = sockets[1];
-       fds[0].events = POLLIN;
-       for (;;) {
-               thread_print(id, "Polling");
-               if ((n = poll(fds, 1, -1)) == -1) {
-                       perror("poll()");
-                       return NULL;
-               }
-               thread_print(id, "Poll returned");
-               if (n == 0) {
-                       thread_print(id, "Woke up! (no data)");
-                       continue;
-               }
-               if ((fds[0].revents & POLLIN) != 0) {
-                       /* Attempt to read event/byte */
-                       thread_print(id, "Woke up! (with data)");
-                       pthread_mutex_lock(&sockets_mutex);
-                       while ((n = read(sockets[1], &c, 1)) == 1)
-                               thread_print(id, "Read data!");
-                       if (n == -1)
-                               thread_print(id, strerror(errno));
-                       pthread_mutex_unlock(&sockets_mutex);
-               }
-       }
-}
-
-/* ARGSUSED */
-static void *
-thread_notify(void *args)
-{
-       char            c = '\0';
-       struct pollfd   fds[1];
-
-       fds[0].fd = sockets[0];
-       fds[0].events = POLLOUT;
-       for (;;) {
-               sleep(1);
-               thread_print(-1, "Notifying");
-               pthread_mutex_lock(&sockets_mutex);
-               if (write(sockets[0], &c, 1) != 1) {
-                       /* Poll until we can send data */
-                       (void) poll(fds, 1, -1);
-               }
-               pthread_mutex_unlock(&sockets_mutex);
-       }
-}
-
-static void
-thread_print(int id, const char *str)
-{
-
-       pthread_mutex_lock(&print_mutex);
-       printf("%d: %s\n", id, str);
-       pthread_mutex_unlock(&print_mutex);
-}
diff --git a/tests/pthread_utils/tests/sigtest.c b/tests/pthread_utils/tests/sigtest.c
deleted file mode 100644 (file)
index cc4b681..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * The goal of this program is to verify if it is valid for multiple threads
- * to be awaken from a poll(2) call by a single process-wide signal. This
- * would allow the notifyer of a thread message event to generate this signal
- * if needed to cause interested treads to wake up. Threads which do not want
- * to receive the signal can simply ignore it using pthread_sigmask().
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <pthread.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-
-
-#define THREADS        8
-
-
-
-int            main(void);
-static void    *thread_poll(void *);
-static void    *thread_notify(void *);
-static void    thread_print(int, const char *);
-
-
-
-static int             sockets[2];
-static int             threadargs[THREADS];
-static pthread_mutex_t print_mutex;
-static pthread_mutex_t sockets_mutex;
-
-
-
-int
-main(void)
-{
-       pthread_t       threadid;
-       int             i;
-
-       /*
-        * Create socketpair which will be used to trigger events to awaken
-        * polling threads.
-        */
-       if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, sockets) != 0) {
-               perror("socketpair()");
-               exit(EXIT_FAILURE);
-       }
-       if (fcntl(sockets[0], F_SETFL, O_NONBLOCK) != 0 ||
-           fcntl(sockets[1], F_SETFL, O_NONBLOCK) != 0) {
-               perror("fcntl()");
-               exit(EXIT_FAILURE);
-       }
-
-       pthread_mutex_init(&print_mutex, NULL);
-       pthread_mutex_init(&sockets_mutex, NULL);
-
-       /*
-        * First launch THREADS polling threads
-        */
-       for (i = 0; i < THREADS; i++) {
-               threadargs[i] = i;
-               pthread_create(&threadid, NULL, thread_poll, &threadargs[i]);
-       }
-       sleep(1);
-
-       /*
-        * And finally launch notifyer thread
-        */
-       pthread_create(&threadid, NULL, thread_notify, NULL);
-
-       /*
-        * Now just wait
-        */
-       for (;;)
-               (void) pause();
-}
-
-static void *
-thread_poll(void *args)
-{
-       struct pollfd   fds[1];
-       int             n;
-       int             id = *(int *)args;
-       char            c;
-
-       fds[0].fd = sockets[1];
-       fds[0].events = POLLIN;
-       for (;;) {
-               thread_print(id, "Polling");
-               if ((n = poll(fds, 1, -1)) == -1) {
-                       perror("poll()");
-                       return NULL;
-               }
-               thread_print(id, "Poll returned");
-               if (n == 0) {
-                       thread_print(id, "Woke up! (no data)");
-                       continue;
-               }
-               if ((fds[0].revents & POLLIN) != 0) {
-                       /* Attempt to read event/byte */
-                       thread_print(id, "Woke up! (with data)");
-                       pthread_mutex_lock(&sockets_mutex);
-                       while ((n = read(sockets[1], &c, 1)) == 1)
-                               thread_print(id, "Read data!");
-                       if (n == -1)
-                               thread_print(id, strerror(errno));
-                       pthread_mutex_unlock(&sockets_mutex);
-               }
-       }
-}
-
-/* ARGSUSED */
-static void *
-thread_notify(void *args)
-{
-       char            c = '\0';
-       struct pollfd   fds[1];
-
-       fds[0].fd = sockets[0];
-       fds[0].events = POLLOUT;
-       for (;;) {
-               sleep(1);
-               thread_print(-1, "Notifying");
-               pthread_mutex_lock(&sockets_mutex);
-               if (write(sockets[0], &c, 1) != 1) {
-                       /* Poll until we can send data */
-                       (void) poll(fds, 1, -1);
-               }
-               pthread_mutex_unlock(&sockets_mutex);
-       }
-}
-
-static void
-thread_print(int id, const char *str)
-{
-
-       pthread_mutex_lock(&print_mutex);
-       printf("%d: %s\n", id, str);
-       pthread_mutex_unlock(&print_mutex);
-}
diff --git a/tests/rotate/GNUmakefile b/tests/rotate/GNUmakefile
deleted file mode 100644 (file)
index 41ca002..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-# $Id: GNUmakefile,v 1.2 2006/05/06 12:25:02 mmondor Exp $
-
-CC := cc
-RM := rm
-UNAME := uname
-
-CFLAGS += -Wall
-
-# Enable for verbosity/debugging
-#CFLAGS += -v -H -g
-#LDFLAGS += -v -g
-
-# And to disable assertions
-CFLAGS += -DNDEBUG
-
-OBJS := main.o
-BINS := rotate
-CBINS := $(addsuffix .exe,$(BINS))
-
-SDL_CFLAGS := $(shell sdl-config --cflags)
-SDL_LDFLAGS := $(shell sdl-config --libs)
-SDL_LDFLAGS += -lSDL_gfx
-
-# OS dependent settings follow
-OS := $(shell $(UNAME) -s)
-ifneq (,$(findstring CYGWIN,$(OS)))
-       # cygwin-mingw
-       CFLAGS += -mno-cygwin -I/usr/include/mingw
-       LDFLAGS += -mwindows -mno-cygwin -L/usr/lib/mingw -L/usr/local/lib
-#      GL_CFLAGS :=
-#      GL_LDFLAGS := -lopengl32 -lglu32
-else
-       # unix
-       CFLAGS += -I/usr/include -I/usr/pkg/include -I/usr/X11R6/include
-       LDFLAGS += -L/usr/lib -L/usr/pkg/lib -L/usr/X11R6/lib
-#      GL_CFLAGS :=
-#      GL_LDFLAGS := -lGL -lGLU
-endif
-
-#CFLAGS += $(SDL_CFLAGS) $(GL_CFLAGS)
-#LDFLAGS += $(SDL_LDFLAGS) $(GL_LDFLAGS)
-CFLAGS += $(SDL_CFLAGS)
-LDFLAGS += $(SDL_LDFLAGS)
-
-all: $(BINS)
-
-%.o: %.c
-       $(CC) -c $(CFLAGS) -I. -o $@ $<
-
-#$(BINS): $(OBJS)
-#      $(CC) -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS)
-
-$(BINS): $(OBJS)
-       $(CC) -o $@ $(OBJS) $(LDFLAGS)
-
-clean:
-       $(RM) -f $(BINS) $(CBINS) $(OBJS) stdout.txt stderr.txt
diff --git a/tests/rotate/main.c b/tests/rotate/main.c
deleted file mode 100644 (file)
index b2ed875..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/* $Id: main.c,v 1.1 2006/05/06 12:25:02 mmondor Exp $ */
-
-/*
- * Copyright (C) 2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <SDL.h>
-#include <SDL_rotozoom.h>
-#include <SDL_gfxPrimitives.h>
-
-
-
-int                    main(int, char **);
-
-
-
-static SDL_Surface     *screen_surface;
-
-
-
-int
-main(int argc, char **argv)
-{
-       SDL_Surface     *s, *save;
-       int             a, ad, at;
-       size_t          fnlen;
-       char            *fnbuf, *file;
-
-       if (argc != 3) {
-               (void) fprintf(stderr, "Usage: rotate \"<file>\" <steps>\n");
-               exit(EXIT_FAILURE);
-       }
-
-       if ((file = strdup(argv[1])) != NULL) {
-               char    *cptr;
-
-               if ((cptr = strrchr(file, '.')) != NULL)
-                       *cptr = '\0';
-       } else {
-               (void) fprintf(stderr, "strdup(%s)\n", argv[1]);
-               exit(EXIT_FAILURE);
-       }
-
-       fnlen = strlen(file) + 16;
-       if ((fnbuf = malloc(fnlen)) == NULL) {
-               (void) fprintf(stderr, "fnbuf = malloc(%d)\n", (int)fnlen + 8);
-               exit(EXIT_FAILURE);
-       }
-
-       at = (double)strtol(argv[2], NULL, 10);
-       ad = (360 / at);
-       if (at * ad != 360) {
-               (void) fprintf(stderr, "<steps> must be a divisor of 360\n");
-               exit(EXIT_FAILURE);
-       }
-
-       if (SDL_Init(SDL_INIT_VIDEO) == -1) {
-               (void) fprintf(stderr, "SDL_Init() - %s\n", SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-       if ((screen_surface = SDL_SetVideoMode(640, 480, 32, SDL_DOUBLEBUF))
-           == NULL) {
-               (void) fprintf(stderr, "SDL_SetVideoMode() - %s\n",
-                   SDL_GetError());
-               goto err;
-       }
-
-       if ((s = SDL_LoadBMP(argv[1])) == NULL) {
-               (void) fprintf(stderr, "SDL_LoadBMP(%s) - %s",
-                   argv[1], SDL_GetError());
-               goto err;
-       }
-       if ((save = SDL_CreateRGBSurface(SDL_SWSURFACE, s->w, s->h, 32,
-           s->format->Rmask, s->format->Gmask, s->format->Bmask,
-           s->format->Amask)) == NULL) {
-               (void) fprintf(stderr, "SDL_CreateRGBSurface() - %s\n",
-                   SDL_GetError());
-               goto err;
-       }
-
-       /*
-        * XXX Assumes 0x000000 is the trasparent color, should probably be
-        * part of the command line parameters.
-        */
-       {
-               Uint32  col;
-
-               col = SDL_MapRGB(s->format, 0x00, 0x00, 0x00);
-               if (SDL_SetColorKey(s, SDL_SRCCOLORKEY, col) == -1) {
-                       (void) fprintf(stderr, "SDL_SetColorKey() - %s\n",
-                           SDL_GetError());
-                       goto err;
-               }
-       }
-
-       for (a = 0; a < 360; a += ad) {
-               SDL_Surface     *t;
-               SDL_Rect        d;
-               int             cx, cy, c;
-
-               cx = s->w / 2;
-               cy = s->h / 2;
-               c = (cx >= cy ? cx : cy);
-
-               /*
-                * XXX Again assumes that 0x000000 color is transparent.
-                * Moreover, in a future version, we also could allow to scale
-                * the bitmap image as wanted...
-                */
-               if (boxRGBA(save, 0, 0, s->w - 1, s->h - 1,
-                   0x00, 0x00, 0x00, 0xff) != 0 ||
-                   boxRGBA(screen_surface, 320 - c, 240 - c, 320 + c, 240 + c,
-                   0x00, 0x00, 0x00, 0xff) != 0) {
-                       (void) fprintf(stderr, "boxRGBA() - %s\n",
-                           SDL_GetError());
-                       goto err;
-               }
-
-               if ((t = rotozoomSurface(s, (double)-a, 1.0, 1)) == NULL) {
-                       (void) fprintf(stderr, "rotozoomSurface() - %s\n",
-                           SDL_GetError());
-                       goto err;
-               }
-               d = (SDL_Rect){320 - (t->w / 2), 240 - (t->h / 2), 0, 0};
-               if (SDL_BlitSurface(t, NULL, screen_surface, &d) != 0) {
-                       (void) fprintf(stderr, "SDL_BlitSurface() - %s\n",
-                           SDL_GetError());
-                       goto err;
-               }
-               SDL_FreeSurface(t);
-
-               d = (SDL_Rect){320 - c, 240 - c, 320 + c, 240 + c};
-               if (SDL_BlitSurface(screen_surface, &d, save, NULL) != 0) {
-                       (void) fprintf(stderr, "SDL_BlitSurface() - %s\n",
-                           SDL_GetError());
-                       goto err;
-               }
-               (void) snprintf(fnbuf, fnlen - 1, "%s-%03d.bmp", file, (int)a);
-               if (SDL_SaveBMP(save, fnbuf) != 0) {
-                       (void) fprintf(stderr, "SDL_SaveBMP(%s) - %s\n",
-                           fnbuf, SDL_GetError());
-                       goto err;
-               }
-
-               if (SDL_Flip(screen_surface) != 0) {
-                       (void) fprintf(stderr, "SDL_Flip() - %s",
-                           SDL_GetError());
-                       goto err;
-               }
-       }
-
-       SDL_Quit();
-       exit(EXIT_SUCCESS);
-
-err:
-       SDL_Quit();
-       exit(EXIT_FAILURE);
-}
diff --git a/tests/sdl-client/GNUmakefile b/tests/sdl-client/GNUmakefile
deleted file mode 100644 (file)
index e316dd3..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-# $Id: GNUmakefile,v 1.31 2006/05/23 01:32:50 mmondor Exp $
-
-CC := cc
-RM := rm
-UNAME := uname
-TOUCH := touch
-OBJDUMP := objdump
-OBJCOPY := objcopy
-GREP := grep
-AWK := awk
-DATE := date
-STRIP := strip
-
-TMPDIR := /tmp
-
-CFLAGS += -Wall
-
-# Enable for verbosity/debugging
-#CFLAGS += -v -H -g
-#LDFLAGS += -v -g
-
-# And to disable assertions
-CFLAGS += -DNDEBUG
-CFLAGS += -g
-
-OBJS := main.o debug.o pool.o thread_msg.o thread_net_recv.o \
-       thread_net_send.o screen.o decode.o
-BINS := client
-CBINS := $(addsuffix .exe,$(BINS))
-RAWOBJS := bmp/RomDD.bmp.enc.o bmp/FedCA.bmp.enc.o wav/nt_cloaked.wav.enc.o \
-       wav/nt_uncloak.wav.enc.o wav/nt_shield_up.wav.enc.o \
-       wav/nt_shield_down.wav.enc.o wav/nt_fire_torp_other.wav.enc.o \
-       wav/nt_plasma_hit.wav.enc.o wav/nt_explosion_other.wav.enc.o \
-       fnt/7x13.fnt.enc.o
-
-SDL_CFLAGS := $(shell sdl-config --cflags)
-SDL_LDFLAGS := $(shell sdl-config --libs)
-SDL_LDFLAGS += -lSDL_image -lSDL_mixer -lSDL_net -lSDL_gfx
-
-# OS dependent settings follow
-OS := $(shell $(UNAME) -s)
-ifneq (,$(findstring CYGWIN,$(OS)))
-       # cygwin-mingw
-       CFLAGS += -mno-cygwin -I/usr/include/mingw -DWIN32
-       LDFLAGS += -mwindows -mno-cygwin -L/usr/lib/mingw -L/usr/local/lib
-#      GL_CFLAGS :=
-#      GL_LDFLAGS := -lopengl32 -lglu32
-else
-       # unix
-       CFLAGS += -I/usr/include -I/usr/pkg/include -I/usr/X11R6/include
-       LDFLAGS += -L/usr/lib -L/usr/pkg/lib -L/usr/X11R6/lib
-#      GL_CFLAGS :=
-#      GL_LDFLAGS := -lGL -lGLU
-endif
-
-# Determine target of compiled objects so that we may convert binaries
-# to compatible objects using objcopy and then link them like other modules.
-OBJTARGET := $(shell $(TOUCH) $(TMPDIR)/obj.c && \
-       $(CC) $(CFLAGS) -c -o $(TMPDIR)/obj.o $(TMPDIR)/obj.c && \
-       $(OBJDUMP) -t $(TMPDIR)/obj.o | \
-       $(GREP) 'file format' | $(AWK) '{print $$4}' \
-       && $(RM) $(TMPDIR)/obj.o $(TMPDIR)/obj.c)
-OBJARCH := $(shell echo $(OBJTARGET) | $(AWK) -F '-' '{print $$2}')
-SEED := $(shell date +%s)
-
-#CFLAGS += $(SDL_CFLAGS) $(GL_CFLAGS)
-#LDFLAGS += $(SDL_LDFLAGS) $(GL_LDFLAGS)
-CFLAGS += $(SDL_CFLAGS)
-LDFLAGS += $(SDL_LDFLAGS)
-
-all: $(BINS)
-
-%.o: %.c
-       $(CC) -c $(CFLAGS) -I. -o $@ $<
-
-encode:
-       $(CC) -o encode encode.c
-
-$(RAWOBJS): encode
-       ./encode $(basename $(basename $@)) $(basename $@) $(SEED)
-       $(OBJCOPY) -I binary -B $(OBJARCH) -O $(OBJTARGET) $(basename $@) $@
-       $(RM) -f $(basename $@)
-
-$(BINS): $(OBJS) $(RAWOBJS)
-       $(CC) -o $@ $(OBJS) $(RAWOBJS) $(LDFLAGS)
-       $(STRIP) -s -w -R .comment -R .ident -R .debug* $@*
-
-clean:
-       $(RM) -f $(BINS) $(CBINS) $(OBJS) $(RAWOBJS) encode encode.exe \
-               stdout.txt stderr.txt
diff --git a/tests/sdl-client/README b/tests/sdl-client/README
deleted file mode 100644 (file)
index 222484f..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-$Id: README,v 1.16 2006/05/23 01:32:50 mmondor Exp $
-
-An attempt to develop a portable game client using SDL among unix
-and windows operating systems.  The only officially supported
-compiler should be GCC (and mingw under windows, avoiding the need
-for cygwin libraries).  The compiling/development environment when
-under windows will use cygwin to provide a shell, vim and cvs,
-while compile options will be specified as needed for it to use
-the mingw compiler (which also comes as part of cygwin).
-
-Initial tests will be using SDL, SDL_mixer and SDL_net.
-
-If all works well, it should also be easy to use OpenGL portably.
-I was already able to get portable SDL/OpenGL code working, a while
-ago, but this generated no sound and had no network requirements.
-Hence this test.
-
-Moreover, the test server under kqueue/ needed a client for further
-testing to be possible at its development stage.
-
-Since SDL_net does not provide non-blocking I/O (and it remains
-unclear if windows supports this properly), a decision was made to
-port to SDL an inter-thread messaging library I had done for use
-with POSIX threads, and to use multiple threads.
-
-One thread will be used to send data to the server, another thread
-to receive data form the server, yet another thread to deal with
-all user input events, and a main thread to receive all those events
-in an asynchroneous manner form the utility threads and run the
-main loop.
-
-04:21 <@lucca> one thread to send, one thread to receive, one thread to poll
-           for io events, and one thread to bring them all and in the darkness
-           bind them.
-
-:)
-
-Ogg-vorbis will be used for music, using SDL_mixer.  Ship rotations
-will be performed using SDL_gfx.
-
-It is very important to avoid having to link this client statically
-against GPL or LGPL libraries, because of the viral nature of those
-licenses.  I do not intend to release my code under those licenses.
-If it ever publically is released, it shall be done under a MIT/BSD
-derived license.
-
-I am also thinking about dedicating a thread for the connect state
-to the server, or possibly to have the writer or reader thread also
-perform that task.
-
-It is possible that a thread be ideal for rendering as well.  It
-could be notified when a screen refresh is wanted, when it could
-set a flag.  When it's time for it to draw a frame (honoring FPS),
-it would if the flag is set, or perhaps it simply could when it
-wants.  I wonder if it would be appropriate for the display thread
-to not need a mutex, since it would always be read-only accessing
-the data.
-
-Anticipated design so far:
-       Main thread
-       User events thread
-       Network receive thread
-       Network Send/Connect thread
-       Display thread (the Receive thread will draw for now).
-
-It is possible that states may be desired.  For instance, there
-would be the connection state, the one where the user and client
-have to provide authentication information (this could be part of
-connect phase perhaps), and in-game state.
-
-At first, as a test, the world will all be seen by everyone and
-will fit into their screen.  A world of 1024x768 could be used for
-this :) Then there will probably be addition of a chat system with
-messages window, to continue enhancing the protocol.  Things will
-go on from there...
-
-Hmm for now I want to simply use a joypad.
-- Button 0 fires in direction of the paddle direction.
-- Buttons 1 and 3 could act like button 0, to provide secondary weapon (1)
-  and special weapon (3).
-- Button 2 attempts to correct navigation direction in the direction
-  of the paddle.
-- Button 6 would accelerate.
-- Button 7 would decelerate.
-- Button 4 could toggle shields
-- Button 5 could toggle cloak
-
-Equivalent keyboard layout:
-- uiojlm,. would change angle just like the gamepad directions.
-- w would toggle cloak
-- s would toggle shield
-- z would thrust up
-- a would thrust down
-- d would cause direction change
-- space would torp
-- f would fire second weapon
-- g would fire special weapon
-
-And we're already out of buttons, we can't beam up/down armies or
-bomb.  Unless button 3 was special instead of a special weapon,
-and allowed to perform various commands depending on the paddle
-direction (i.e. up/down to beam up/down, left to bomb).  This also
-means that orbiting/launching would need to be automatic.  Of course
-all this is if we're thinking about a game like netrek.  But we'll
-simply only allow dogfighting at first.
-
-Now it becomes tricky how I'll minimize bandwidth sent from the
-client to the server.  Probably that buttons events will be monitored,
-and then current paddle direction when required.  In the case of
-direction change button, the last paddle direction applied would
-be remembered, and if the same, the event could be dropped.  If
-not, send a direction change packet.  What happens if a button
-remains pressed while a direction change occurs?  We probably should
-ignore it.
-
-
-Threading limitations under win32
-=================================
-
-There seem to be bugs when using SDL with multiple threads under windows
-which I did not observe on unix systems.  The docs specify that the main
-thread should perform the drawing, but it wasn't specified that another
-thread than the initial one would not be able to obtain all user input
-events on windows.  Typed keys would not be received, for instance.
-
-It then appears that most of the processing must be done in the main
-initial thread, while only networking related blocking functions will
-be done in slave threads.
-
-There also seem to be other windows-specific problems using SDL threads,
-such as instability.  I have noticed that when using another thread
-for user events reception, part of the application would often lockup,
-despite my code properly using mutexes as required, and all sound and
-greaphics being performed by the main initial thread nevertheless.
-These problems were also not found to occur on unix systems.
-
-The design was thus changed for now, and threads will be used for SDL_net
-functions only, since they are blocking.  Let's hope that this will work
-stably, however.  It remains to be tested.
-
-
-Storing images and sound samples as part of the executable binary
-=================================================================
-
-I was able to include read-only (.rodata) and read-write (.data) into
-binaries directly from files using objcopy and linking them on NetBSD,
-Linux and cygwin-mingw.  The SDL_image library, which I now successfully
-built for mingw, includes functions that can use RWops, and the SDL
-library allows to easily create RWops from memory buffers.  Moreover, the
-SDL_mixer library also allows to do this to load sound samples.  I should
-thus modify the makefiles and code to very easily use these features.
-
-The SDL_mixer library however does not allow by itself to do this easily
-with music files.  However, thise generally being considerably larger,
-it should not be a problem and they can remain external.
-
-If this works fine, it would be easy to generate a cryptographic block
-cipher key at build time and to include that key within the executable
-as well.  Copies of the binary files to be included could then be
-encrypted using that cipher to a temporary copy which will be linked
-in, and an initialization function could be provided to unencrypt the
-files prior to use.  Of course, since the key is also in the executable,
-there is no real security.  However, it could prevent computer-illiterate
-people from too easily ripping our original content.  RC4 could be used
-for this for instance, or even a much more simple custom encoding
-algorithm :)
-
-
-Using a map
-===========
-
-We probably want to randomize the ship's positions on the map.
-Randomization in this respect could be done on a position in a
-circle of varied radius distance to the location of the actual
-ship.  This would prevent clients from being able to exactly fire
-at the actual ship position using the map (which also would make
-cloaking useful against an unofficial client).
-
-
-PROGRAMMING STYLE
-=================
-
-The style chosen for this project consists of the (Net)BSD KNF style
-(Kernel Normal Form) style borrowed from.  All code should conform to it.
-Additionally, lint(1)-style comments are used to make the code clearer
-for future code auditors.
-
-
-
-Matt
diff --git a/tests/sdl-client/bmp/FedCA.bmp b/tests/sdl-client/bmp/FedCA.bmp
deleted file mode 100644 (file)
index be3a562..0000000
Binary files a/tests/sdl-client/bmp/FedCA.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/README b/tests/sdl-client/bmp/README
deleted file mode 100644 (file)
index 4f0b49d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-For these tests, the winxp ships library were borrowed temporarily.
diff --git a/tests/sdl-client/bmp/RomDD.bmp b/tests/sdl-client/bmp/RomDD.bmp
deleted file mode 100644 (file)
index 50e429a..0000000
Binary files a/tests/sdl-client/bmp/RomDD.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/fedship.bmp b/tests/sdl-client/bmp/fedship.bmp
deleted file mode 100755 (executable)
index 465806f..0000000
Binary files a/tests/sdl-client/bmp/fedship.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/indship.bmp b/tests/sdl-client/bmp/indship.bmp
deleted file mode 100755 (executable)
index 1a7e39b..0000000
Binary files a/tests/sdl-client/bmp/indship.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/kliship.bmp b/tests/sdl-client/bmp/kliship.bmp
deleted file mode 100755 (executable)
index cf52598..0000000
Binary files a/tests/sdl-client/bmp/kliship.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/misc-fixed-bold-r-normal--13-120-75-75-c-80-iso8859-1.bmp b/tests/sdl-client/bmp/misc-fixed-bold-r-normal--13-120-75-75-c-80-iso8859-1.bmp
deleted file mode 100644 (file)
index c55b172..0000000
Binary files a/tests/sdl-client/bmp/misc-fixed-bold-r-normal--13-120-75-75-c-80-iso8859-1.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/misc-fixed-bold-r-normal--15-120-100-100-c-90-iso8859-1.bmp b/tests/sdl-client/bmp/misc-fixed-bold-r-normal--15-120-100-100-c-90-iso8859-1.bmp
deleted file mode 100644 (file)
index 5c2ab05..0000000
Binary files a/tests/sdl-client/bmp/misc-fixed-bold-r-normal--15-120-100-100-c-90-iso8859-1.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-1.bmp b/tests/sdl-client/bmp/misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-1.bmp
deleted file mode 100644 (file)
index e8ac5d4..0000000
Binary files a/tests/sdl-client/bmp/misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-1.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/misc-fixed-medium-r-normal--15-120-100-100-c-90-iso8859-1.bmp b/tests/sdl-client/bmp/misc-fixed-medium-r-normal--15-120-100-100-c-90-iso8859-1.bmp
deleted file mode 100644 (file)
index 9e1d9f2..0000000
Binary files a/tests/sdl-client/bmp/misc-fixed-medium-r-normal--15-120-100-100-c-90-iso8859-1.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/oriship.bmp b/tests/sdl-client/bmp/oriship.bmp
deleted file mode 100755 (executable)
index 166fb1a..0000000
Binary files a/tests/sdl-client/bmp/oriship.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/romship.bmp b/tests/sdl-client/bmp/romship.bmp
deleted file mode 100755 (executable)
index 753d38a..0000000
Binary files a/tests/sdl-client/bmp/romship.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/sbexpl.bmp b/tests/sdl-client/bmp/sbexpl.bmp
deleted file mode 100755 (executable)
index b06ffcf..0000000
Binary files a/tests/sdl-client/bmp/sbexpl.bmp and /dev/null differ
diff --git a/tests/sdl-client/bmp/shexpl.bmp b/tests/sdl-client/bmp/shexpl.bmp
deleted file mode 100755 (executable)
index 72a62c4..0000000
Binary files a/tests/sdl-client/bmp/shexpl.bmp and /dev/null differ
diff --git a/tests/sdl-client/conf.h b/tests/sdl-client/conf.h
deleted file mode 100644 (file)
index e0a91c9..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: conf.h,v 1.6 2006/05/19 11:16:42 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Various hardcoded configuration parameters.
- */
-
-#define SERVER_HOST    "hal.xisop"
-#define SERVER_PORT    7777
diff --git a/tests/sdl-client/debug.c b/tests/sdl-client/debug.c
deleted file mode 100644 (file)
index 4dd5bae..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/* $Id: debug.c,v 1.2 2006/05/19 09:16:14 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-
-
-#ifndef NDEBUG
-void
-debug(const char *file, const char *func, int line, const char *fmt, ...)
-{
-       va_list lst;
-       char    buf[1024];
-
-       va_start(lst, fmt);
-       vsnprintf(buf, 1023, fmt, lst);
-       va_end(lst);
-       (void) fprintf(stderr, "%s:%s():%d - %s\n", file, func, line, buf);
-}
-
-void
-debug2(const char *file, const char *func, int line, const char *fmt, ...)
-{
-       va_list lst;
-       char    buf[1024];
-
-       va_start(lst, fmt);
-       vsnprintf(buf, 1023, fmt, lst);
-       va_end(lst);
-       (void) fprintf(stderr, "%s:%s():%d - %s\n", file, func, line, buf);
-
-       exit(EXIT_FAILURE);
-}
-#endif
diff --git a/tests/sdl-client/debug.h b/tests/sdl-client/debug.h
deleted file mode 100644 (file)
index 30827c0..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* $Id: debug.h,v 1.2 2006/05/19 09:36:57 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#ifndef DEBUG_H
-#define DEBUG_H
-
-
-
-#ifndef NDEBUG
-
-/*
- * Macro similar to assert(3) but which does not exit the application. Will
- * instead log the condition unless DEBUG_ASSERT_ABORT is set.
- * Moreover, the aborting one actually simply calls exit(2) after logging the
- * error instead of generating a SIGABRT signal.
- */
-#ifdef ASSERT_ABORT
-#define ASSERT(c)              if (!(c))                               \
-   debug2(__FILE__, __func__, __LINE__, "ASSERT(" #c ") == %d", c);
-#else
-#define ASSERT(c)              if (!(c))                               \
-   debug(__FILE__, __func__, __LINE__, "ASSERT(" #c ") == %d", c);
-#endif
-
-#else
-
-#define ASSERT(c)              ;
-
-#endif
-
-
-
-void   debug(const char *, const char *, int, const char *, ...);
-void   debug2(const char *, const char *, int, const char *, ...);
-
-
-
-#endif
diff --git a/tests/sdl-client/decode.c b/tests/sdl-client/decode.c
deleted file mode 100644 (file)
index f0b0bc4..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/* $Id: decode.c,v 1.2 2006/05/10 01:28:01 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Function to easily decode data processed by the encode command.
- */
-
-
-
-#include <stdio.h>
-#include <stdint.h>
-
-#include <decode.h>
-
-
-
-void
-decode(void **ndata, size_t *nsize, void *data, size_t size)
-{
-       uint8_t *ptr, *tptr, *key;
-
-       ptr = (uint8_t *)data;
-       *ndata = &ptr[4];
-       *nsize = size - 4;
-
-       for (key = ptr, ptr = &ptr[4], tptr = &ptr[*nsize];
-           ptr < tptr; ptr++) {
-               *ptr ^= key[0] ^ key[1] ^ key[2] ^ key[3];
-               key[0]--;
-               key[1]++;
-               key[2] -= 3;
-               key[3] += 3;
-       }
-}
diff --git a/tests/sdl-client/decode.h b/tests/sdl-client/decode.h
deleted file mode 100644 (file)
index ab5f3b6..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: decode.h,v 1.1 2006/05/10 00:48:40 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Function to easily decode data processed by the encode command.
- */
-
-
-
-#ifndef DECODE_H
-#define DECODE_H
-
-
-
-void   decode(void **, size_t *, void *, size_t);
-
-
-
-#endif
diff --git a/tests/sdl-client/dlist.h b/tests/sdl-client/dlist.h
deleted file mode 100644 (file)
index a3bc766..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/* $Id: dlist.h,v 1.5 2006/04/27 10:59:19 mmondor Exp $ */
-
-/*
- * Copyright (C) 2001-2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#ifndef DLIST_H
-#define DLIST_H
-
-
-
-typedef struct list    list_t;
-typedef struct node    node_t;
-
-
-
-struct node {
-       node_t          *prev, *next;
-};
-
-struct list {
-       node_t          *top, *bottom;
-       int             nodes;
-};
-
-
-
-/* Some macros to optimize operations on doubly linked lists */
-#define DLIST_INITIALIZER      {NULL, NULL, 0}
-
-#define DLIST_INIT(lst)                do {                                    \
-       (lst)->top = (lst)->bottom = NULL;                              \
-       (lst)->nodes = 0;                                               \
-} while (/* CONSTCOND */0)
-
-#define DLIST_UNLINK(lst, nod) do {                                    \
-       register node_t *prev = (nod)->prev, *next = (nod)->next;       \
-                                                                       \
-       if (prev != NULL)                                               \
-               prev->next = next;                                      \
-       else                                                            \
-               (lst)->top = next;                                      \
-       if (next != NULL)                                               \
-               next->prev = prev;                                      \
-       else                                                            \
-               (lst)->bottom = prev;                                   \
-       (lst)->nodes--;                                                 \
-} while (/* CONSTCOND */0)
-
-#define DLIST_APPEND(lst, nod) do {                                    \
-       register node_t *tmp = (lst)->bottom;                           \
-                                                                       \
-       if (tmp != NULL) {                                              \
-               tmp->next = (nod);                                      \
-               (nod)->prev = tmp;                                      \
-               (nod)->next = NULL;                                     \
-               (lst)->bottom = (nod);                                  \
-       } else {                                                        \
-               (lst)->bottom = (lst)->top = (nod);                     \
-               (nod)->next = (nod)->prev = NULL;                       \
-       }                                                               \
-       (lst)->nodes++;                                                 \
-} while (/* CONSTCOND */0)
-
-#define DLIST_INSERT(lst, nod) do {                                    \
-       register node_t *tmp = (lst)->top;                              \
-                                                                       \
-       if (tmp != NULL) {                                              \
-               tmp->prev = (nod);                                      \
-               (nod)->prev = NULL;                                     \
-               (nod)->next = tmp;                                      \
-               (lst)->top = (nod);                                     \
-       } else {                                                        \
-               (lst)->top = (lst)->bottom = (nod);                     \
-               (nod)->next = (nod)->prev = NULL;                       \
-       }                                                               \
-       (lst)->nodes++;                                                 \
-} while (/* CONSTCOND */0)
-
-#define DLIST_INSERTAT(lst, atnode, nod) do {                          \
-       register node_t *prev = (atnode)->prev, *next = (atnode);       \
-                                                                       \
-       (nod)->next = next;                                             \
-       next->prev = (nod);                                             \
-       if (prev != NULL) {                                             \
-               prev->next = (nod);                                     \
-               (nod)->prev = prev;                                     \
-       } else {                                                        \
-               (lst)->top = (nod);                                     \
-               (nod)->prev = NULL;                                     \
-       }                                                               \
-       (lst)->nodes++;                                                 \
-} while (/* CONSTCOND */0)
-
-#define DLIST_SWAP(dst, src, nod, ins) do {                            \
-       register node_t *prev = (nod)->prev, *next = (nod)->next;       \
-                                                                       \
-       if (prev != NULL)                                               \
-               prev->next = next;                                      \
-       else                                                            \
-               (src)->top = next;                                      \
-       if (next != NULL)                                               \
-               next->prev = prev;                                      \
-       else                                                            \
-               (src)->bottom = prev;                                   \
-       (src)->nodes--;                                                 \
-       if ((ins)) {                                                    \
-               if ((prev = (dst)->top) != NULL) {                      \
-                       prev->prev = (nod);                             \
-                       (nod)->prev = NULL;                             \
-                       (nod)->next = prev;                             \
-                       (dst)->top = (nod);                             \
-               } else {                                                \
-                       (dst)->top = (dst)->bottom = (nod);             \
-                       (nod)->next = (nod)->prev = NULL;               \
-               }                                                       \
-       } else {                                                        \
-               if ((prev = (dst)->bottom) != NULL) {                   \
-                       prev->next = (nod);                             \
-                       (nod)->prev = prev;                             \
-                       (nod)->next = NULL;                             \
-                       (dst)->bottom = (nod);                          \
-               } else {                                                \
-                       (dst)->bottom = (dst)->top = (nod);             \
-                       (nod)->next = (nod)->prev = NULL;               \
-               }                                                       \
-       }                                                               \
-       (dst)->nodes++;                                                 \
-} while (/* CONSTCOND */0)
-
-#define DLIST_TOP(lst)         ((void *)((list_t *)(lst))->top)
-#define DLIST_BOTTOM(lst)      ((void *)((list_t *)(lst))->bottom)
-#define DLIST_NEXT(var)                ((void *)((node_t *)(var))->next)
-#define DLIST_PREV(var)                ((void *)((node_t *)(var))->prev)
-
-#define DLIST_FOREACH(lst, var)                                                \
-    for ((var) = DLIST_TOP((lst)); (var) != NULL; (var) = DLIST_NEXT((var)))
-
-#define DLIST_NODES(lst)       (((list_t *)(lst))->nodes)
-
-
-
-#endif
diff --git a/tests/sdl-client/encode.c b/tests/sdl-client/encode.c
deleted file mode 100644 (file)
index 66701da..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/* $Id: encode.c,v 1.4 2006/05/19 03:35:43 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHT RESERVED.
- */
-
-/*
- * Very simple encoding algorithm.  Given a 32-bit key,
- * it will encode the supplied file using XOR encoding and changing
- * the integer values.
- * For even more simplicity, the key is randomly generated and stored as
- * part of the output file as the first four bytes :)
- * This really shouldn't be considered encryption, it merely is simple
- * encoding for computer-illiterates to not too easily rip our images
- * and sound samples.
- */
-
-
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-
-
-#define        BUF_SIZE        65536
-
-
-
-int    main(int, char **);
-void   encode(uint8_t *, size_t, uint8_t *key);
-
-
-
-int
-main(int argc, char **argv)
-{
-       FILE            *ifh, *ofh;
-       uint8_t         key[4], *buf;
-       size_t          s;
-
-       if (argc != 4) {
-               (void) fprintf(stderr,
-                   "Usage: encode <infile> <outfile> <seed>\n");
-               exit(EXIT_FAILURE);
-       }
-
-       if ((buf = malloc(BUF_SIZE)) == NULL) {
-               (void) fprintf(stderr,
-                   "Could not allocate %d bytes\n", BUF_SIZE);
-               exit(EXIT_FAILURE);
-       }
-
-       if ((ifh = fopen(argv[1], "r")) == NULL) {
-               (void) fprintf(stderr,
-                   "Cannot open '%s' for reading\n", argv[1]);
-               exit(EXIT_FAILURE);
-       }
-
-       if ((ofh = fopen(argv[2], "w")) == NULL) {
-               (void) fprintf(stderr,
-                   "Cannot open '%s' for writing\n", argv[2]);
-               exit(EXIT_FAILURE);
-       }
-
-       /* Generate random key and write it to output file */
-       srand((unsigned int)strtoul(argv[3], NULL, 10));
-       key[0] = rand() & 0xff;
-       key[1] = rand() & 0xff;
-       key[2] = rand() & 0xff;
-       key[3] = rand() & 0xff;
-       if (fwrite(key, 1, 4, ofh) != 4) {
-               (void) fprintf(stderr,
-                   "Error writing key to '%s'\n", argv[2]);
-               exit(EXIT_FAILURE);
-       }
-
-       while ((s = fread(buf, 1, BUF_SIZE, ifh)) > 0) {
-               encode(buf, s, key);
-               if (fwrite(buf, 1, s, ofh) != s) {
-                       (void) fprintf(stderr,
-                           "Error writing to '%s'\n", argv[2]);
-                       exit(EXIT_FAILURE);
-               }
-       }
-
-       (void) fclose(ofh);
-       (void) fclose(ifh);
-       free(buf);
-
-       exit(EXIT_SUCCESS);
-}
-
-void
-encode(uint8_t *data, size_t size, uint8_t *key)
-{
-       uint8_t *tdata;
-
-       for (tdata = data + size; data < tdata; data++) {
-               *data ^= key[0] ^ key[1] ^ key[2] ^ key[3];
-               key[0]--;
-               key[1]++;
-               key[2] -= 3;
-               key[3] += 3;
-       }
-}
diff --git a/tests/sdl-client/fnt/10x20.fnt b/tests/sdl-client/fnt/10x20.fnt
deleted file mode 100644 (file)
index 99b3486..0000000
Binary files a/tests/sdl-client/fnt/10x20.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/5x7.fnt b/tests/sdl-client/fnt/5x7.fnt
deleted file mode 100644 (file)
index 3612165..0000000
Binary files a/tests/sdl-client/fnt/5x7.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/5x8.fnt b/tests/sdl-client/fnt/5x8.fnt
deleted file mode 100644 (file)
index 01add72..0000000
Binary files a/tests/sdl-client/fnt/5x8.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/6x10.fnt b/tests/sdl-client/fnt/6x10.fnt
deleted file mode 100644 (file)
index 3c49f20..0000000
Binary files a/tests/sdl-client/fnt/6x10.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/6x12.fnt b/tests/sdl-client/fnt/6x12.fnt
deleted file mode 100644 (file)
index 156865b..0000000
Binary files a/tests/sdl-client/fnt/6x12.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/6x13.fnt b/tests/sdl-client/fnt/6x13.fnt
deleted file mode 100644 (file)
index e259f1a..0000000
Binary files a/tests/sdl-client/fnt/6x13.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/6x13B.fnt b/tests/sdl-client/fnt/6x13B.fnt
deleted file mode 100644 (file)
index 503b773..0000000
Binary files a/tests/sdl-client/fnt/6x13B.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/6x13O.fnt b/tests/sdl-client/fnt/6x13O.fnt
deleted file mode 100644 (file)
index cb5a27f..0000000
Binary files a/tests/sdl-client/fnt/6x13O.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/6x9.fnt b/tests/sdl-client/fnt/6x9.fnt
deleted file mode 100644 (file)
index cca4689..0000000
Binary files a/tests/sdl-client/fnt/6x9.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/7x13.fnt b/tests/sdl-client/fnt/7x13.fnt
deleted file mode 100644 (file)
index d20852e..0000000
Binary files a/tests/sdl-client/fnt/7x13.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/7x13B.fnt b/tests/sdl-client/fnt/7x13B.fnt
deleted file mode 100644 (file)
index 9f3fbed..0000000
Binary files a/tests/sdl-client/fnt/7x13B.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/7x13O.fnt b/tests/sdl-client/fnt/7x13O.fnt
deleted file mode 100644 (file)
index e5b7732..0000000
Binary files a/tests/sdl-client/fnt/7x13O.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/7x14.fnt b/tests/sdl-client/fnt/7x14.fnt
deleted file mode 100644 (file)
index fdcd752..0000000
Binary files a/tests/sdl-client/fnt/7x14.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/7x14B.fnt b/tests/sdl-client/fnt/7x14B.fnt
deleted file mode 100644 (file)
index 939aa63..0000000
Binary files a/tests/sdl-client/fnt/7x14B.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/8x13.fnt b/tests/sdl-client/fnt/8x13.fnt
deleted file mode 100644 (file)
index 9de72b4..0000000
Binary files a/tests/sdl-client/fnt/8x13.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/8x13B.fnt b/tests/sdl-client/fnt/8x13B.fnt
deleted file mode 100644 (file)
index 96179a0..0000000
Binary files a/tests/sdl-client/fnt/8x13B.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/8x13O.fnt b/tests/sdl-client/fnt/8x13O.fnt
deleted file mode 100644 (file)
index a38a371..0000000
Binary files a/tests/sdl-client/fnt/8x13O.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/9x15.fnt b/tests/sdl-client/fnt/9x15.fnt
deleted file mode 100644 (file)
index 349e5bd..0000000
Binary files a/tests/sdl-client/fnt/9x15.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/9x15B.fnt b/tests/sdl-client/fnt/9x15B.fnt
deleted file mode 100644 (file)
index 23bc97e..0000000
Binary files a/tests/sdl-client/fnt/9x15B.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/9x18.fnt b/tests/sdl-client/fnt/9x18.fnt
deleted file mode 100644 (file)
index 0651c97..0000000
Binary files a/tests/sdl-client/fnt/9x18.fnt and /dev/null differ
diff --git a/tests/sdl-client/fnt/9x18B.fnt b/tests/sdl-client/fnt/9x18B.fnt
deleted file mode 100644 (file)
index d93d09d..0000000
Binary files a/tests/sdl-client/fnt/9x18B.fnt and /dev/null differ
diff --git a/tests/sdl-client/main.c b/tests/sdl-client/main.c
deleted file mode 100644 (file)
index 100de1c..0000000
+++ /dev/null
@@ -1,872 +0,0 @@
-/* $Id: main.c,v 1.73 2006/05/23 01:32:50 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-/* STANDARD HEADERS */
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* THIRD PARTY LIBRARY HEADERS */
-#include <SDL.h>
-#include <SDL_image.h>
-#include <SDL_thread.h>
-#include <SDL_rotozoom.h>
-#include <SDL_gfxPrimitives.h>
-#include <SDL_framerate.h>
-#include <SDL_mixer.h>
-#include <SDL_net.h>
-
-/* APPLICATION HEADERS */
-#include <main.h>
-#include <debug.h>
-#include <screen.h>
-#include <packets.h>
-#include <thread_msg.h>
-#include <thread_net_recv.h>
-#include <thread_net_send.h>
-#include <rawobjs.h>
-#include <decode.h>
-
-
-
-/* DEFINITIONS */
-
-enum userevents {
-       UE_FPS
-};
-
-struct font {
-       int     w, h;
-       void    *data;
-       size_t  size;
-};
-
-#define        VECTOR_X(x, a, r)       ((int)(x) + (cos_table[(a)] * (r)))
-#define        VECTOR_Y(y, a, r)       ((int)(y) + (sin_table[(a)] * (r)))
-
-
-
-/* PRIVATE PROTOTYPES */
-
-int                    main(int, char **);
-
-static void            axis_angle_update(void);
-static void            handle_uevent(SDL_Event *);
-static void            handle_recvmsg(thread_amsg_t *);
-static void            objects_update(void);
-static void            frame_clear(void);
-static void            frame_draw(void);
-
-static int             surface_blit_angle(SDL_Surface *, int, int, double,
-                           int);
-static SDL_Surface     *bmp_load_key(void *, size_t);
-
-static Mix_Chunk       *sample_load(void *, size_t);
-
-static struct font     *font_load(void *, size_t, int, int);
-static void            font_blit_string(struct font *, int, int,
-                           const char *, uint8_t, uint8_t, uint8_t, uint8_t);
-
-static Uint32          fpscnt_callback(Uint32, void *);
-
-static void            trig_init(void);
-
-
-
-/* PUBLIC GLOBALS */
-
-thread_port_t          main_port;
-
-
-
-/* PRIVATE GLOBALS */
-
-static int             joy_angle = 0;
-
-static int             shields = 0, cloaked = 0, nav_thrust = 0,
-                       cur_nav_thrust = 0, nav_angle = 0,
-                       cur_nav_angle = 0, nav_pos_x = 512, nav_pos_y = 384,
-                       max_thrust = 12;
-static SDL_Surface     *rship, *fship;
-
-static Mix_Chunk       *snd_cloak, *snd_uncloak, *snd_shield, *snd_unshield,
-                       *snd_torp, *snd_hit, *snd_explode;
-
-static FPSmanager      fpsh;
-static SDL_TimerID     fpst;
-static char            fpsstr[8];
-static int             fpscnt;
-
-static struct font     *font;
-
-static double          cos_table[360], sin_table[360];
-static int             fired = 0;
-
-
-
-/* PRIVATE FUNCTIONS */
-
-/* ARGSUSED */
-int
-main(int argc, char **argv)
-{
-       thread_ring_t   main_ring;
-       SDL_Thread      *recv_threadid, *send_threadid;
-       Mix_Music       *mus;
-
-       /* Initialization */
-       screen_init();
-       trig_init();
-       (void) SDL_ShowCursor(0);
-       (void) SDL_EnableKeyRepeat(0, 0);
-
-       /*
-        * Ignore a few events with potentially high frequency but which
-        * we don't need
-        */
-       (void) SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
-       (void) SDL_EventState(SDL_JOYAXISMOTION, SDL_IGNORE);
-       (void) SDL_EventState(SDL_JOYBALLMOTION, SDL_IGNORE);
-       (void) SDL_EventState(SDL_JOYHATMOTION, SDL_IGNORE);
-       (void) SDL_EventState(SDL_KEYUP, SDL_IGNORE);
-
-       /*
-        * Network
-        */
-       if (SDLNet_Init() != 0) {
-               (void) fprintf(stderr, "main() - SDLNet_Init() - %s\n",
-                   SDLNet_GetError());
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * Audio
-        */
-       if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024) != 0) {
-               (void) fprintf(stderr, "main() - Mix_OpenAudio() - %s\n",
-                   Mix_GetError());
-               exit(EXIT_FAILURE);
-       }
-       snd_cloak = sample_load((void *)&_binary_wav_nt_cloaked_wav_enc_start,
-           (size_t)&_binary_wav_nt_cloaked_wav_enc_size);
-       snd_uncloak = sample_load(
-           (void *)&_binary_wav_nt_uncloak_wav_enc_start,
-           (size_t)&_binary_wav_nt_uncloak_wav_enc_size);
-       snd_shield = sample_load(
-           (void *)&_binary_wav_nt_shield_up_wav_enc_start,
-           (size_t)&_binary_wav_nt_shield_up_wav_enc_size);
-       snd_unshield = sample_load(
-           (void *)&_binary_wav_nt_shield_down_wav_enc_start,
-           (size_t)&_binary_wav_nt_shield_down_wav_enc_size);
-       snd_torp = sample_load(
-           (void *)&_binary_wav_nt_fire_torp_other_wav_enc_start,
-           (size_t)&_binary_wav_nt_fire_torp_other_wav_enc_size);
-       snd_hit = sample_load((void *)&_binary_wav_nt_plasma_hit_wav_enc_start,
-           (size_t)&_binary_wav_nt_plasma_hit_wav_enc_size);
-       snd_explode = sample_load(
-           (void *)&_binary_wav_nt_explosion_other_wav_enc_start,
-           (size_t)&_binary_wav_nt_explosion_other_wav_enc_size);
-       (void) Mix_AllocateChannels(16);
-       (void) Mix_ReserveChannels(2);
-       if ((mus = Mix_LoadMUS("ogg/1.ogg")) == NULL) {
-               (void) fprintf(stderr, "main() - Mix_LoadMUS() - %s\n",
-                   Mix_GetError());
-               exit(EXIT_FAILURE);
-       }
-       if (Mix_PlayMusic(mus, -1) != 0) {
-               (void) fprintf(stderr, "main() - Mix_PlayMusic() - %s\n",
-                   Mix_GetError());
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * Bitmap graphics
-        */
-       rship = bmp_load_key((void *)&_binary_bmp_RomDD_bmp_enc_start,
-           (size_t)&_binary_bmp_RomDD_bmp_enc_size);
-       fship = bmp_load_key((void *)&_binary_bmp_FedCA_bmp_enc_start,
-           (size_t)&_binary_bmp_FedCA_bmp_enc_size);
-
-       /*
-        * Bitmap fonts
-        */
-       font = font_load((void *)&_binary_fnt_7x13_fnt_enc_start,
-           (size_t)&_binary_fnt_7x13_fnt_enc_size, 7, 13);
-
-       /*
-        * We're already the main thread.
-        * Initialize our message port and notification ring.
-        */
-       if (thread_ring_init(&main_ring) == -1) {
-               (void) fprintf(stderr,
-                   "main() - thread_ring_init(main_port) - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-       if (thread_port_init(&main_port) == -1) {
-               (void) fprintf(stderr,
-                   "main() - thread_port_init(main_port) - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-       thread_port_set_ring(&main_port, &main_ring);
-
-       /* XXX We should obtain user login information */
-
-       if (thread_amsg_pool_init() != 0) {
-               (void) fprintf(stderr, "main() - thread_amsg_init()\n");
-               exit(EXIT_FAILURE);
-       }
-
-       /* Launch network utility threads */
-       if ((recv_threadid = SDL_CreateThread(thread_net_recv, NULL))
-           == NULL) {
-               (void) fprintf(stderr,
-                   "main() - SDL_CreateThread(thread_net_recv) - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-       if ((send_threadid = SDL_CreateThread(thread_net_send, NULL))
-           == NULL) {
-               (void) fprintf(stderr,
-                   "main() - SDL_CreateThread(thread_net_send) - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * XXX Wait until we receive the server's connection status.
-        * We should display a "connecting to server" or such message to the
-        * user during this time.
-        */
-       {
-               struct msg_connect      *cmsg;
-
-               while ((cmsg = (struct msg_connect *)thread_msg_get(
-                   &main_port)) == NULL)
-                       (void) thread_ring_wait(&main_ring, -1);
-
-               if (cmsg->status == -1) {
-                       (void) fprintf(stderr, "%s\n", cmsg->error);
-                       exit(EXIT_FAILURE);
-               }
-
-               (void) thread_msg_reply(&cmsg->msg);
-       }
-
-       /* FPS counter initialization */
-       (void) strcpy(fpsstr, "000 fps");
-       fpscnt = 0;
-       fpst = SDL_AddTimer(5000, fpscnt_callback, NULL);
-
-       /* FPS management initialization */
-       SDL_initFramerate(&fpsh);
-       SDL_setFramerate(&fpsh, 10);
-
-       /*
-        * Main loop.
-        * Listen for messages and events and process them, while drawing
-        * frames.
-        *
-        * XXX There remain design choices to make here.
-        * We could only draw a frame once we received all data for a frame
-        * from the server, thus waiting for the EndOfFrame message to draw,
-        * in which case we only need to bother drawing the current new
-        * received data.  If we did this, we potentially could reduce the
-        * incomming asynchroneous messages rate so that a single one is sent
-        * once every messages for a frame were obtained.  This method would
-        * probably be the most efficient, while allowing the client to update
-        * its display as fast as it is able to obtain the server information
-        * for a frame.  However, this also means that for a very large world,
-        * if a map exists or such, there could be more data needing to be
-        * sent per frame, unless there also were in a frame the information
-        * to update the existing world information, which would be similar to
-        * the second method.  Hmm since we need to send a difference packet
-        * for every object on the map, or to possibly resend their position,
-        * what could be done is having the server sending updates less
-        * frequently for that data.  Although, we would need to make sure to
-        * avoid causing lag to the normal 10fps display when
-        * sending/processing large map packets.  We possibly could
-        * intermingle some map information data per normal frame, having the
-        * server round-robin the map information among the clients in a
-        * distributed way?  Say we have 50 connected clients, and that we
-        * want a map update rate of approximately 1 second interval, we could
-        * send the data among them at 50 / 10, meaning that we send each
-        * client update of 5 clients.  With round robin this means that every
-        * client, 10 times per second are receiving enough update information
-        * so that within a second the whole map be updated.  Of course, we
-        * would need not to break this when clients connect/disconnect.
-        *
-        * Or, we could instead maintain our own known world and display
-        * states and only update them via the messages received from the
-        * server, allowing us to maintain a steady frame rate (although this
-        * would also mean that no change could be made between certain
-        * frames).
-        */
-       for (;;) {
-               thread_amsg_t   *amsg;
-               SDL_Event       ev;
-
-               /* Process incomming server messages. */
-               while ((amsg = (thread_amsg_t *)thread_msg_get(&main_port))
-                   != NULL) {
-                       handle_recvmsg(amsg);
-                       thread_amsg_destroy(amsg);
-               }
-
-               /* Update gamepad current angle. */
-               if (gamepad != NULL)
-                       axis_angle_update();
-
-               /*
-                * Process incomming user events, sending corresponding
-                * messages to the server when appropriate.
-                */
-               while (SDL_PollEvent(&ev))
-                       handle_uevent(&ev);
-
-               /*
-                * XXX Probably to be done on the server, but such a step
-                * might still be necessary perhaps.
-                * Update objects position in preparation to draw the current
-                * frame.
-                */
-               objects_update();
-
-               /*
-                * Draw current frame and wait until it's time to draw another
-                * frame.
-                */
-               frame_draw();
-               SDL_framerateDelay(&fpsh);
-       }
-       /* NOTREACHED */
-
-       thread_port_set_ring(&main_port, NULL);
-       thread_port_destroy(&main_port);
-       thread_ring_destroy(&main_ring);
-
-       exit(EXIT_SUCCESS);
-}
-
-static void
-axis_angle_update(void)
-{
-       int     angle, x, y;
-
-       angle = joy_angle;
-
-       /* On win32 -1 is reported for dead state instead of 0! */
-       if ((x = SDL_JoystickGetAxis(gamepad, 0)) > 127)
-               x = 1;
-       else if (x < -128)
-               x = -1;
-       else
-               x = 0;
-
-       if ((y = SDL_JoystickGetAxis(gamepad, 1)) > 127)
-               y = 1;
-       else if (y < -128)
-               y = -1;
-       else
-               y = 0;
-
-       if (x == 0 && y == 0)
-               return;
-       if (x == 0 && y == -1)
-               angle = 0;
-       else if (x == 1 && y == -1)
-               angle = 45;
-       else if (x == 1 && y == 0)
-               angle = 90;
-       else if (x == 1 && y == 1)
-               angle = 135;
-       else if (x == 0 && y == 1)
-               angle = 180;
-       else if (x == -1 && y == 1)
-               angle = 225;
-       else if (x == -1 && y == 0)
-               angle = 270;
-       else if (x == -1 && y == -1)
-               angle = 315;
-
-       if (joy_angle != angle)
-               joy_angle = angle;
-
-       return;
-}
-
-static void
-handle_uevent(SDL_Event *ev)
-{
-
-       if (ev->type == SDL_MOUSEMOTION)
-           return;
-
-       /*
-        * Quit commands events.
-        */
-       if ((ev->type == SDL_KEYDOWN && ev->key.keysym.sym == SDLK_ESCAPE) ||
-           ev->type == SDL_QUIT)
-               exit(EXIT_FAILURE);
-
-       /*
-        * Button events.  joy_angle affects several of them.
-        * We currently ignore release events.
-        */
-       if (ev->type == SDL_JOYBUTTONDOWN) {
-               int     ch;
-
-               if (ev->jbutton.state != 1)
-                       return;
-
-               switch (ev->jbutton.button) {
-               case 0:
-                       /* Torp */
-                       if ((ch = Mix_PlayChannel(-1, snd_torp, 0)) != -1)
-                               Mix_SetPosition(ch, joy_angle, 50);
-                       fired = 1;
-                       break;
-               case 1:
-                       /* Secondary weapon */
-                       if ((ch = Mix_PlayChannel(-1, snd_hit, 0)) != -1)
-                               Mix_SetPosition(ch, joy_angle, 50);
-                       break;
-               case 2:
-                       /* Navigation direction change */
-                       if (nav_angle != joy_angle)
-                               nav_angle = joy_angle;
-                       break;
-               case 3:
-                       /* Special weapon */
-                       if ((ch = Mix_PlayChannel(-1, snd_explode, 0)) != -1)
-                               Mix_SetPosition(ch, joy_angle, 50);
-                       break;
-               case 4:
-                       /* Toggle shields */
-                       shields = (shields == 0 ? 1 : 0);
-                       Mix_PlayChannel(1,
-                           (shields == 1 ? snd_shield : snd_unshield), 0);
-                       break;
-               case 5:
-                       /* Toggle cloak */
-                       cloaked = (cloaked == 0 ? 1 : 0);
-                       Mix_PlayChannel(2,
-                           (cloaked == 1 ? snd_cloak : snd_uncloak), 0);
-                       break;
-               case 6:
-                       /* Thrust accelerate */
-                       if (nav_thrust < max_thrust)
-                               nav_thrust++;
-                       break;
-               case 7:
-                       /* Thrust decelerate */
-                       if (nav_thrust > 0)
-                               nav_thrust--;
-                       break;
-               }
-
-               return;
-       }
-
-       /*
-        * Keyboard events
-        */
-       if (ev->type == SDL_KEYDOWN) {
-               int     angle = joy_angle, ch;
-
-               switch (ev->key.keysym.sym) {
-               /* Angle changes */
-               case SDLK_i:
-                       angle = 0;
-                       break;
-               case SDLK_o:
-                       angle = 45;
-                       break;
-               case SDLK_l:
-                       angle = 90;
-                       break;
-               case SDLK_PERIOD:
-                       angle = 135;
-                       break;
-               case SDLK_COMMA:
-                       angle = 180;
-                       break;
-               case SDLK_m:
-                       angle = 225;
-                       break;
-               case SDLK_j:
-                       angle = 270;
-                       break;
-               case SDLK_u:
-                       angle = 315;
-                       break;
-               /* Navigation change */
-               case SDLK_d:
-                       /* Direction */
-                       if (nav_angle != joy_angle)
-                               nav_angle = joy_angle;
-                       break;
-               case SDLK_z:
-                       /* Thrust up */
-                       if (nav_thrust < max_thrust)
-                               nav_thrust++;
-                       break;
-               case SDLK_a:
-                       /* Thrust down */
-                       if (nav_thrust > 0)
-                               nav_thrust--;
-                       break;
-               /* Weapons */
-               case SDLK_SPACE:
-                       /* Torp */
-                       if ((ch = Mix_PlayChannel(-1, snd_torp, 0)) != -1)
-                               Mix_SetPosition(ch, joy_angle, 50);
-                       fired = 1;
-                       break;
-               case SDLK_f:
-                       /* Secondary weapon */
-                       if ((ch = Mix_PlayChannel(-1, snd_hit, 0)) != -1)
-                               Mix_SetPosition(ch, joy_angle, 50);
-                       break;
-               case SDLK_g:
-                       /* Special weapon */
-                       if ((ch = Mix_PlayChannel(-1, snd_explode, 0)) != -1)
-                               Mix_SetPosition(ch, joy_angle, 50);
-                       break;
-               /* Toggles */
-               case SDLK_s:
-                       /* Shield */
-                       shields = (shields == 0 ? 1 : 0);
-                       Mix_PlayChannel(1,
-                           (shields == 1 ? snd_shield : snd_unshield), 0);
-                       break;
-               case SDLK_w:
-                       /* Cloak */
-                       cloaked = (cloaked == 0 ? 1 : 0);
-                       Mix_PlayChannel(2,
-                           (cloaked == 1 ? snd_cloak : snd_uncloak), 0);
-                       break;
-               default:
-                       break;
-               }
-
-               if (joy_angle != angle)
-                       joy_angle = angle;
-               return;
-       }
-
-}
-
-static void
-handle_recvmsg(thread_amsg_t *amsg)
-{
-
-       /* XXX */
-       if (amsg->size != -1)
-               (void) fwrite(amsg->data, amsg->size, 1, stdout);
-       else {
-               (void) fprintf(stderr, "Error reading from server socket\n");
-               exit(EXIT_FAILURE);
-       }
-}
-
-/*
- * These will normally occur on the server.
- * However, it's nice for temporary testing.
- */
-static void
-objects_update(void)
-{
-
-       /*
-        * XXX
-        * Adjust current thrust according to ship's acceleration/deceleration
-        * speeds in order to eventually reach nav_thrust.  It seems that
-        * we need floating point variables to perform this.
-        */
-       if (cur_nav_thrust != nav_thrust) {
-               if (cur_nav_thrust < nav_thrust)
-                       cur_nav_thrust++;
-               else
-                       cur_nav_thrust--;
-       }
-
-       /*
-        * XXX
-        * For now we also should use cos/sin and allow the ship to move
-        * around in its current direction at its current thrust.
-        * We should also bounce when reaching the borders for now,
-        * by reversing its angle.
-        */
-       if (cur_nav_thrust != 0) {
-               nav_pos_x = VECTOR_X(nav_pos_x, cur_nav_angle,
-                   cur_nav_thrust + 1);
-               nav_pos_y = VECTOR_Y(nav_pos_y, cur_nav_angle,
-                   cur_nav_thrust + 1);
-       }
-
-       /*
-        * XXX
-        * We need to rotate cur_nav_angle in the shortest direction to
-        * nav_angle, while making sure to always have angles in the range
-        * 0 - 359 only.  Moreover, if the degrees stepped are too large
-        * to exactly reach nav_angle, we want to just reach it at the last
-        * step.  To properly test the later condition, we step relatively
-        * to the current thrust.
-        */
-       if (cur_nav_angle != nav_angle) {
-               if (cur_nav_angle < nav_angle) {
-                       if ((cur_nav_angle += (max_thrust + 10) -
-                           cur_nav_thrust) > nav_angle)
-                               cur_nav_angle = nav_angle;
-               } else {
-                       if ((cur_nav_angle -= (max_thrust + 10) -
-                           cur_nav_thrust) < nav_angle)
-                               cur_nav_angle = nav_angle;
-               }
-       }
-}
-
-static void
-frame_clear(void)
-{
-       uint32_t        *ptr, *tptr;
-
-       /*
-       for (ptr = screen_surface->pixels,
-           tptr = &ptr[screen_width * screen_height];
-           ptr < tptr; ) {
-               *ptr++ = 0x00000000;
-               *ptr++ = 0x00000000;
-               *ptr++ = 0x00000000;
-               *ptr++ = 0x00000000;
-               *ptr++ = 0x00000000;
-               *ptr++ = 0x00000000;
-               *ptr++ = 0x00000000;
-               *ptr++ = 0x00000000;
-       }
-       */
-
-       for (ptr = screen_surface->pixels,
-           tptr = &ptr[screen_width * screen_height];
-           ptr < tptr; ptr = &ptr[8]) {
-               ptr[0] = 0x00000000;
-               ptr[1] = 0x00000000;
-               ptr[2] = 0x00000000;
-               ptr[3] = 0x00000000;
-               ptr[4] = 0x00000000;
-               ptr[5] = 0x00000000;
-               ptr[6] = 0x00000000;
-               ptr[7] = 0x00000000;
-       }
-}
-
-static void
-frame_draw(void)
-{
-
-       frame_clear();
-       /* SDL_FillRect(screen_surface, NULL, 0); */
-
-       surface_blit_angle(rship, nav_pos_x, nav_pos_y, cur_nav_angle, 0);
-       if (cloaked)
-               filledCircleRGBA(screen_surface, nav_pos_x, nav_pos_y, 25,
-                   0x00, 0x00, 0x00, 0x80);
-       if (shields) {
-               aacircleRGBA(screen_surface, nav_pos_x, nav_pos_y, 25,
-                   0xe0, 0xe0, 0x20, 0x60);
-               filledCircleRGBA(screen_surface, nav_pos_x, nav_pos_y, 25,
-                   0xf0, 0xf0, 0x30, 0x40);
-       }
-       aalineRGBA(screen_surface,
-           VECTOR_X(nav_pos_x, cur_nav_angle, 40),
-           VECTOR_Y(nav_pos_y, cur_nav_angle, 40),
-           VECTOR_X(nav_pos_x, cur_nav_angle, 60),
-           VECTOR_Y(nav_pos_y, cur_nav_angle, 60),
-           0xff, 0xff, 0xff, 0x80);
-
-       if (fired) {
-               int     i;
-
-               fired = 0;
-               for (i = 0; i < 255; i++) {
-                       pixelRGBA(screen_surface,
-                           VECTOR_X(nav_pos_x, joy_angle, i),
-                           VECTOR_Y(nav_pos_y, joy_angle, i),
-                           0xff, 0xff, 0x00, 0xff - i);
-               }
-       }
-
-       {
-               char    str[256];
-
-               (void) snprintf(str, 255,
-                   "Thrust: %02d/%02d (%02d), "
-                   "Angle: %03d (%03d), "
-                   "Position: (%03d,%03d), "
-                   "Shields: %3s, "
-                   "Cloak: %3s",
-                   cur_nav_thrust, max_thrust, nav_thrust,
-                   cur_nav_angle, nav_angle,
-                   nav_pos_x, nav_pos_y,
-                   (shields == 1 ? "On" : "Off"),
-                   (cloaked == 1 ? "On" : "Off"));
-               font_blit_string(font, 17, 17, str,
-                   0x00, 0x00, 0x00, 0xff);
-               font_blit_string(font, 16, 16, str,
-                   0xff, 0xff, 0xff, 0xff);
-       }
-
-       font_blit_string(font, 17, 741, fpsstr, 0x00, 0x00, 0x00, 0xff);
-       font_blit_string(font, 16, 740, fpsstr, 0xff, 0xff, 0xff, 0xff);
-
-       (void) SDL_Flip(screen_surface);
-       fpscnt++;
-}
-
-static SDL_Surface *
-bmp_load_key(void *data, size_t size)
-{
-       SDL_RWops       *rwo;
-       SDL_Surface     *s;
-       Uint32          c;
-       void            *ndata;
-       size_t          nsize;
-
-       decode(&ndata, &nsize, data, size);
-
-       if ((rwo = SDL_RWFromMem(ndata, nsize)) == NULL)
-               goto err;
-       if ((s = IMG_LoadBMP_RW(rwo)) == NULL)
-               goto err;
-       SDL_FreeRW(rwo);
-
-       c = SDL_MapRGB(s->format, 0, 0, 0);
-       if (SDL_SetColorKey(s, SDL_SRCCOLORKEY | SDL_RLEACCEL, c) == -1)
-               goto err;
-
-       return s;
-
-err:
-       (void) fprintf(stderr, "bmp_load_key() - %s\n", SDL_GetError());
-       exit(EXIT_FAILURE);
-}
-
-static int
-surface_blit_angle(SDL_Surface *s, int x, int y, double a, int clean)
-{
-       SDL_Surface     *t;
-       SDL_Rect        d;
-       int             r;
-
-       ASSERT(a > -1 && a < 360);
-
-       if (clean) {
-               int     cx, cy, c;
-
-               cx = s->w / 2 + 2;
-               cy = s->h / 2 + 2;
-               c = (cx >= cy ? cx : cy);
-               (void) boxRGBA(screen_surface, x - c, y - c,
-                   x + c, y + c, 0x00, 0x00, 0x00, 0xff);
-       }
-
-       if ((t = rotozoomSurface(s, -a, 1.0, 1)) != NULL) {
-               d = (SDL_Rect){x - (t->w / 2), y - (t->h / 2), 0, 0};
-               r = SDL_BlitSurface(t, NULL, screen_surface, &d);
-               SDL_FreeSurface(t);
-       } else
-               r = -1;
-
-       return r;
-}
-
-static Mix_Chunk *
-sample_load(void *data, size_t size)
-{
-       SDL_RWops       *rwo;
-       Mix_Chunk       *c;
-       void            *ndata;
-       size_t          nsize;
-
-       decode(&ndata, &nsize, data, size);
-
-       if ((rwo = SDL_RWFromMem(ndata, nsize)) == NULL)
-               goto err;
-
-       if ((c = Mix_LoadWAV_RW(rwo, 0)) == NULL)
-               goto err;
-
-       SDL_FreeRW(rwo);
-       return c;
-
-err:
-       (void) fprintf(stderr, "sample_load() - %s\n", SDL_GetError());
-       exit(EXIT_FAILURE);
-}
-
-static struct font *
-font_load(void *data, size_t size, int width, int height)
-{
-       struct font     *font;
-       void            *ndata;
-       size_t          nsize;
-
-       decode(&ndata, &nsize, data, size);
-
-       if ((font = malloc(sizeof(struct font))) == NULL)
-               goto err;
-
-       font->data = ndata;
-       font->w = width;
-       font->h = height;
-       font->size = nsize;
-       return font;
-
-err:
-       (void) fprintf(stderr, "font_load()\n");
-       exit(EXIT_FAILURE);
-}
-
-static void
-font_blit_string(struct font *font, int x, int y, const char *str,
-    uint8_t r, uint8_t g, uint8_t b, uint8_t a)
-{
-
-       (void) gfxPrimitivesSetFont(font->data, font->w, font->h);
-       (void) stringRGBA(screen_surface, x, y, str, r, g, b, a);
-}
-
-/* ARGSUSED */
-static Uint32
-fpscnt_callback(Uint32 interval, void *args)
-{
-
-       (void) sprintf(fpsstr, "%03d fps", fpscnt / 5);
-       fpscnt = 0;
-
-       return interval;
-}
-
-/* Initialize trigonometric tables */
-static void
-trig_init(void)
-{
-       int     i;
-       double  f;
-
-       for (i = 0; i < 360; i++) {
-               f = ((2 * M_PI) / 360) * (i - 90);
-               sin_table[i] = sin(f);
-               cos_table[i] = cos(f);
-       }
-}
diff --git a/tests/sdl-client/main.h b/tests/sdl-client/main.h
deleted file mode 100644 (file)
index 12b8cb2..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* $Id: main.h,v 1.3 2006/05/19 09:13:42 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Exported resources by the main program, mainly for thread modules.
- */
-
-
-
-#ifndef MAIN_H
-#define MAIN_H
-
-
-
-#include <SDL.h>
-
-#include <thread_msg.h>
-
-
-
-extern thread_port_t   main_port;
-
-
-
-#endif
diff --git a/tests/sdl-client/ogg/README b/tests/sdl-client/ogg/README
deleted file mode 100644 (file)
index 90d493c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-For how, place any ogg track that you like as 1.ogg under this directory.
-Eventually there shall be some of my own composed music, when I have time
-and care enough to add it.
-
-Matt
diff --git a/tests/sdl-client/packets.c b/tests/sdl-client/packets.c
deleted file mode 100644 (file)
index 0a46921..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/* $Id: packets.c,v 1.1 2006/05/19 09:13:42 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * To validate a received packet, we'll make sure that it's larger than
- * sizeof(int), and that the first integer consists of a valid expected packet
- * type ID within range.  If so, we verify if packet length really corresponds
- * to the packet type, and then can interpret the packet information.
- * An actual network packet may contain a number of these packets.
- * We thus must be able to efficiently determine each packet's length.
- * Since we're using TCP, it should be enough.  However, on the server side
- * especially, proper sanity checking on input must be done to avoid crashing
- * the server because of unexpected data processing.
- */
-
-
-
-#include <stdlib.h>
-
-#include <mmstring.h>
-#include <mmarch.h>
-
-#include "packets.h"
-#include "client.h"
-#include "sendq.h"
-#include "conf.h"
-
-
-
-static int     cpacket_auth_handler(client_t *, uint16_t *);
-static int     cpacket_ping_handler(client_t *, uint16_t *);
-static int     cpacket_pong_handler(client_t *, uint16_t *);
-static int     cpacket_direction_handler(client_t *, uint16_t *);
-static int     cpacket_thrust_handler(client_t *, uint16_t *);
-static int     cpacket_torp_handler(client_t *, uint16_t *);
-static int     cpacket_quit_handler(client_t *, uint16_t *);
-
-
-
-static struct packet_index     cpacket_index[CPACKET_MAX] = {
-       {sizeof(struct cpacket_auth), cpacket_auth_handler},
-       {sizeof(struct cpacket_ping), cpacket_ping_handler},
-       {sizeof(struct cpacket_pong), cpacket_pong_handler},
-       {sizeof(struct cpacket_direction), cpacket_direction_handler},
-       {sizeof(struct cpacket_thrust), cpacket_thrust_handler},
-       {sizeof(struct cpacket_torp), cpacket_torp_handler},
-       {sizeof(struct cpacket_quit), cpacket_quit_handler}
-};
-
-
-
-void
-update(void)
-{
-       node_t          *nod, *next;
-       client_t        *c;
-       uint8_t         *data;
-       size_t          size, off;
-
-       for (nod = DLIST_TOP(&clients_list); nod != NULL; nod = next) {
-               next = DLIST_NEXT(nod);
-               c = (client_t *)nod;
-
-               if (c->todestroy || c->toclose)
-                       continue;
-
-               /* Reset ping request throttling flag */
-               c->askedping = 0;
-
-               /* First process incomming packets */
-               recvq_content(&c->recvq, &data, &size);
-               for (off = 0; off < size; ) {
-                       int16_t *id;
-
-                       /*
-                        * Verify packet type ID. It already has been
-                        * converted to host endian byte order, unlike other
-                        * packet fields.
-                        */
-                       id = (int16_t *)&data[off];
-                       *id = BYTEORDER_HOST16(*id);
-                       if (*id < 0 || *id > CPACKET_MAX) {
-                               client_destroy_mark(c);
-                               break;
-                       }
-
-                       /* There must be enough data for packet size */
-                       if (size - off < cpacket_index[*id].size) {
-                               /*
-                                * Kill authentucated client if other packets
-                                * than CPACKET_AUTH
-                                */
-                               if (!c->authenticated && *id != CPACKET_AUTH)
-                                       goto k;
-
-                               /*
-                                * XXX We'll need to also do special
-                                * processing for chat packets, since they'll
-                                * have arbitrary length.  They'll still need
-                                * to be 16-bit aligned, too.
-                                */
-
-                               /* Kill client on packet processing error */
-                               if (cpacket_index[*id].handler(c,
-                                   (uint16_t *)off) == -1)
-                                       goto k;
-                       } else
-                               goto k;
-
-                       /* Process next packet if any */
-                       off += cpacket_index[*id].size;
-                       continue;
-
-k:
-                       client_destroy_mark(c);
-                       break;
-               }
-
-               /*
-                * XXX I don't like having to run the clients list all over,
-                * to then run through all objects (including clients) to
-                * update them, and then yet again through all objects to send
-                * updates to all clients.
-                */
-
-               /* Run game frame on all objects */
-               DLIST_FOREACH(&clients_list, nod) {
-                       client_t        *c = (client_t *)nod;
-
-                       /*
-                       if (!c->authenticated)
-                               continue;
-                        */
-
-                       /*
-                        * First update direction and thrust.
-                        * XXX I could do a small function or macro to deal
-                        * with similar situations, i.e.
-                        * change_update(int goal, int *current, int steps);
-                        */
-                       if (c->object.direction < c->object.i_direction)
-                               c->object.direction++;
-                       else if (c->object.direction > c->object.i_direction)
-                               c->object.direction--;
-                       if (c->object.thrust < c->object.i_thrust)
-                               c->object.thrust++;
-                       else if (c->object.thrust > c->object.i_thrust)
-                               c->object.thrust--;
-
-                       /*
-                        * Translate object x/y position according to
-                        * trust/direction.  When reaching borders we simply
-                        * bounce for now.
-                        * (I need to review my trigonometry a bit again :)
-                        */
-                       /* XXX */
-                       c->object.x += 1 - (random() & 2);
-                       if (c->object.x < 0)
-                               c->object.x = 0;
-                       else if (c->object.x > WORLD_X_MAX - 1)
-                               c->object.x = WORLD_X_MAX - 1;
-                       c->object.y += 1 - (random() & 2);
-                       if (c->object.y < 0)
-                               c->object.y = 0;
-                       else if (c->object.y > WORLD_Y_MAX - 1)
-                               c->object.y = WORLD_Y_MAX - 1;
-               }
-
-               /* Send update frame information packets */
-               DLIST_FOREACH(&clients_list, nod) {
-                       client_t        *c = (client_t *)nod;
-                       node_t          *nod2;
-
-                       /*
-                       if (!c->authenticated)
-                               continue;
-                        */
-
-                       DLIST_FOREACH(&clients_list, nod2) {
-                               if (spacket_position_send(c,
-                                   &((client_t *)nod2)->object) == -1)
-                                       break;
-                       }
-                       (void) sendq_flush(&c->sendq, -1);
-               }
-       }
-}
-
-
-int
-spacket_auth_send(client_t *c)
-{
-       struct spacket_auth     p;
-
-       p.packet_type = BYTEORDER_NETWORK16(SPACKET_AUTH);
-       mm_memclr(p.string, 32);
-       mm_strncpy(p.string, SERVER_STRING, 31);
-       p.protocol_version = BYTEORDER_NETWORK16(SERVER_VERSION);
-       /* XXX */
-
-       return client_write(c, (uint8_t *)&p, sizeof(p), 0);
-}
-
-int
-spacket_pong_send(client_t *c)
-{
-       struct spacket_pong     p;
-
-       p.packet_type = BYTEORDER_NETWORK16(SPACKET_PONG);
-
-       return client_write(c, (uint8_t *)&p, sizeof(p), 0);
-}
-
-int
-spacket_position_send(client_t *c, object_t *o)
-{
-       struct spacket_position p;
-
-       p.packet_type = BYTEORDER_NETWORK16(SPACKET_POSITION);
-       p.object_id = p.object_type = BYTEORDER_NETWORK16(0);   /* XXX */
-       p.x = BYTEORDER_NETWORK16(o->x);
-       p.y = BYTEORDER_NETWORK16(o->y);
-       p.direction - BYTEORDER_NETWORK16(o->direction);
-
-       return client_write(c, (uint8_t *)&p, sizeof(p), 1);
-}
-
-
-/* Note that only the packet_type field is endian converted yet. */
-
-static int
-cpacket_auth_handler(client_t *c, uint16_t *ptr)
-{
-       struct cpacket_auth     *p = (struct cpacket_auth *)ptr;
-
-       p->protocol_version = BYTEORDER_HOST16(p->protocol_version);
-
-       if (c->authenticated || p->protocol_version < SERVER_VERSION)
-               return -1;
-
-       /*
-        * XXX For now.  Eventually also check user/password
-        * We could use APOP-like authentication where server sends random
-        * data as part of the authentication greeting/request, and expect
-        * client to append password to random data and send hashed result.
-        * We also should do user concurrency checking here.
-        */
-       c->authenticated = 1;
-
-       return 0;
-}
-
-/*
- * Note: Following function is never used, since pings are handled in the
- * kqueue main loop code.
- */
-/* ARGSUSED */
-static int
-cpacket_ping_handler(client_t *c, uint16_t *ptr)
-{
-       /* NOOP */
-
-       return 0;
-}
-
-static int
-cpacket_pong_handler(client_t *c, uint16_t *ptr)
-{
-/*     struct cpacket_pong     *p = (struct cpacket_pong *)ptr;*/
-
-       /* XXX */
-
-       return 0;
-}
-
-static int
-cpacket_direction_handler(client_t *c, uint16_t *ptr)
-{
-       struct cpacket_direction        *p = (struct cpacket_direction *)ptr;
-
-       p->direction = BYTEORDER_HOST16(p->direction);
-
-       /* Radians */
-       if (p->direction < 0 || p->direction > 1000)
-               return -1;
-
-       c->object.i_direction = p->direction;
-
-       return 0;
-}
-
-static int
-cpacket_thrust_handler(client_t *c, uint16_t *ptr)
-{
-       struct cpacket_thrust   *p = (struct cpacket_thrust *)ptr;
-
-       p->thrust = BYTEORDER_HOST16(p->thrust);
-
-       if (p->thrust < 0 || p->thrust > 20)
-               return -1;
-
-       c->object.i_thrust = p->thrust;
-
-       return 0;
-}
-
-static int
-cpacket_torp_handler(client_t *c, uint16_t *ptr)
-{
-/*     struct cpacket_torp     *p = (struct cpacket_torp *)ptr;*/
-
-       /* XXX */
-
-       return 0;
-}
-
-/* ARGSUSED */
-static int
-cpacket_quit_handler(client_t *c, uint16_t *ptr)
-{
-
-       return -1;
-}
diff --git a/tests/sdl-client/packets.h b/tests/sdl-client/packets.h
deleted file mode 100644 (file)
index 4db2425..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/* $Id: packets.h,v 1.1 2006/05/19 09:13:42 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * All packets must begin with an int16_t packet_type.  All fields of a packet
- * must either be [u]int8_t, [u]int16_t, [u]int32+t or [u]int64_t.  Moreover,
- * all fields will be passed in network/big endian byte order when sent over
- * the network.  We could have used a union, but this would have resulted in
- * larger, fixed sized packets wasting bandwidth.  Since a server to client
- * update will generally involve sending more than one such packet in a row,
- * it is important to minimize their size.
- * Note: If using 32-bit fields within a packet, make sure that they are
- * 32-bit aligned.
- */
-
-
-
-#ifndef _PACKETS_H_
-#define _PACKETS_H_
-
-
-
-#include <stdint.h>
-
-
-
-/*
- * For every server packet type we support, an index array will be used
- * with this structure to call the associated handler function, which will
- * perform sanity checking and process the packet, returning 0 on success or
- * -1 on error.  The size field will allow to perform sanity checking on
- * data size prior to calling the handler function, as well as to increase the
- * buffer pointer.
- */
-struct packet_index {
-       size_t  size;
-       int     (*handler)(uint16_t *);
-};
-
-
-
-/*
- * Server to client packets
- */
-
-enum spacket_types {
-       SPACKET_AUTH = 0,
-       SPACKET_PING,
-       SPACKET_PONG,
-       SPACKET_POSITION,
-       SPACKET_COLLISION,
-       SPACKET_MAX
-};
-
-/* Used to request client authentication and respond success/failure */
-struct spacket_auth {
-       int16_t packet_type;
-       int16_t protocol_version;
-       char    string[32];
-       /* XXX */
-} __attribute__((__packed__));
-
-/* And for server to test idle connections */
-struct spacket_ping {
-       int16_t packet_type;
-} __attribute__((__packed__));
-
-/* And clients to test latency */
-struct spacket_pong {
-       int16_t packet_type;
-} __attribute__((__packed__));
-
-/* Object position/direction update to client */
-struct spacket_position {
-       int16_t packet_type;
-       int16_t object_id, object_type;
-       int16_t x, y, direction;
-} __attribute__((__packed__));
-
-/* Collision/detonation update to client */
-struct spacket_collision {
-       int16_t packet_type;
-       int16_t collision_type;
-       int16_t object1_id, object2_id;
-} __attribute__((__packed__));
-
-
-
-/*
- * Client to server packets
- */
-
-enum cpacket_tyoes {
-       CPACKET_AUTH = 0,
-       CPACKET_PING,
-       CPACKET_PONG,
-       CPACKET_DIRECTION,
-       CPACKET_THRUST,
-       CPACKET_TORP,
-       CPACKET_QUIT,
-       CPACKET_MAX
-};
-
-/* Used to respond to server authentication request */
-struct cpacket_auth {
-       int16_t packet_type;
-       int16_t protocol_version;
-       char    string[32];
-       /* XXX */
-} __attribute__((__packed__));
-
-/* To ping server for latency mesurement */
-struct cpacket_ping {
-       int16_t packet_type;
-} __attribute__((__packed__));
-
-/* To respond to server ping requests */
-struct cpacket_pong {
-       int16_t packet_type;
-} __attribute__((__packed__));
-
-/* Angle/direction change request */
-struct cpacket_direction {
-       int16_t packet_type;
-       int16_t direction;
-} __attribute__((__packed__));
-
-/* Speed change request */
-struct cpacket_thrust {
-       int16_t packet_type;
-       int16_t thrust;
-} __attribute__((__packed__));
-
-/* Torpedo fire request */
-struct cpacket_torp {
-       int16_t packet_type;
-       int16_t direction;
-} __attribute__((__packed__));
-
-/* Game quit request */
-struct cpacket_quit {
-       int16_t packet_type;
-} __attribute__((__packed__));
-
-
-
-#endif
diff --git a/tests/sdl-client/pool.c b/tests/sdl-client/pool.c
deleted file mode 100644 (file)
index 23d7d25..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-/* $Id: pool.c,v 1.3 2006/05/19 09:36:57 mmondor Exp $ */
-
-/*
- * Copyright (C) 2001-2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <dlist.h>
-#include <pool.h>
-#include <debug.h>
-
-
-
-/* DEFINITIONS */
-
-#define BPAGE_SIZE     ((size_t)OALIGN_CEIL(sizeof(bpage_t), long))
-
-
-
-/* STATIC FUNCTION PROTOTYPES */
-
-static bpage_t *       pool_page_create(const char *, pool_t *);
-static bpage_t *       pool_page_destroy(bpage_t *);
-
-
-
-/* STATIC FUNCTIONS */
-
-/*
- * Creates a new page of objects, and calls the constructor function for each
- * object of the new page if needed.  Returns NULL on failure, or the new
- * bpage_t pointer on success.
- */
-static bpage_t *
-pool_page_create(const char *func, pool_t *pool)
-{
-       register size_t         nodesize = pool->nodesize;
-       register uint8_t        *ptr, *toptr;
-       register bpage_t        *page;
-       register list_t         *list;
-
-       if ((page = pool->malloc(pool->pagesize)) == NULL)
-               return NULL;
-
-       /* Initialize bpage_t */
-       page->magic = MAGIC_PAGE;
-       page->pool = pool;
-       DLIST_INIT(&page->objects);
-
-       /*
-        * Create all objects of that bpage_t, inserting them into it's list_t.
-        * If any object creation fails (it's optional construtor function can
-        * fail), destroy the page and return NULL.
-        */
-       if (pool->create != NULL) {
-               for (ptr = toptr = (uint8_t *)page, ptr += BPAGE_SIZE,
-                    toptr += pool->pagesize, list = &page->objects;
-                    ptr + nodesize < toptr; ptr += nodesize) {
-                       ((pnode_t *)ptr)->magic = 0;
-                       ((pnode_t *)ptr)->page = page;
-                       if (pool->create((pnode_t *)ptr) != 0)
-                               return pool_page_destroy(page);
-                       DLIST_APPEND(list, (node_t *)ptr);
-               }
-       } else {
-               for (ptr = toptr = (uint8_t *)page, ptr += BPAGE_SIZE,
-                    toptr += pool->pagesize, list = &page->objects;
-                    ptr + nodesize < toptr; ptr += nodesize) {
-                       ((pnode_t *)ptr)->magic = 0;
-                       ((pnode_t *)ptr)->page = page;
-                       DLIST_APPEND(list, (node_t *)ptr);
-               }
-       }
-
-       return page;
-}
-
-/*
- * Destroys a page previously created using pool_page_create(), calling the
- * destructor function for each object of the page if necessary.
- * Returns NULL.
- */
-static bpage_t *
-pool_page_destroy(bpage_t *page)
-{
-       register pnode_t        *pnode;
-       register void           (*destroy)(pnode_t *);
-
-       if ((destroy = (page->pool->destroy)) != NULL) {
-               /* We need to destroy all objects */
-               DLIST_FOREACH(&page->objects, pnode)
-                  destroy(pnode);
-       }
-
-       page->pool->free(page);
-
-       return NULL;
-}
-
-
-
-/* PUBLIC FUNCTIONS */
-
-/*
- * Initializes a memory pool for efficient management of fixed sized nodes.
- * Returns 0 on success or -1 on failure.
- */
-int
-pool_init(pool_t *pool, const char *label, void *(*mallocfunc)(size_t),
-    void (*freefunc)(void *), int (*create)(pnode_t *),
-    void (*destroy)(pnode_t *), size_t nodesize, uint32_t nodesperpage,
-    uint32_t minpages, uint32_t maxpages)
-{
-       int             ok = -1;
-       register size_t ns, ps;
-
-       ASSERT(!POOL_VALID(pool));
-       ASSERT(pool != NULL && mallocfunc != NULL && freefunc != NULL &&
-           ((create != NULL && destroy != NULL) ||
-            (void *)create == (void *)destroy) &&
-           nodesize != 0 && nodesperpage > 0);
-
-       ns = (size_t)OALIGN_CEIL(nodesize, long);
-       ps = (BPAGE_SIZE + ((nodesperpage + 1) * ns));
-
-       pool->magic = 0;
-       pool->label = label;
-       pool->malloc = mallocfunc;
-       pool->free = freefunc;
-       pool->create = create;
-       pool->destroy = destroy;
-       pool->nodesize = ns;
-       pool->minpages = minpages;
-       pool->maxpages = maxpages;
-       pool->nodesperpage = nodesperpage;
-       pool->pagesize = ps;
-       pool->avgtotal = pool->avgcnt = minpages;
-       DLIST_INIT(&pool->pages);
-       DLIST_INIT(&pool->fpages);
-       DLIST_INIT(&pool->epages);
-
-       /*
-        * Allocate minimum number of pages, if needed. We insert them into
-        * the empty pages list, but minpages will be honored as such to
-        * never free pages below it.
-        */
-       for (; minpages > 0; minpages--) {
-               register bpage_t        *p;
-
-               if ((p = pool_page_create("pool_init", pool)) == NULL)
-                       break;
-               DLIST_APPEND(&pool->epages, (node_t *)p);
-       }
-
-       /* Validate this pool */
-       pool->magic = MAGIC_POOL;
-
-       /*
-        * Have we failed to allocate any needed pages? If so, destroy pool
-        * and return -1.
-        */
-       if (minpages == 0)
-               ok = 0;
-       else if (minpages < pool->minpages)
-               (void) pool_destroy(pool);
-
-       return ok;
-}
-
-
-/*
- * Destroys a pool which previously has been created by pool_init(), and frees
- * any resources it uses (all the nodes it created become invalid).
- */
-void
-pool_destroy(pool_t *pool)
-{
-       register bpage_t        *p, *t;
-
-       ASSERT(POOL_VALID(pool));
-
-       /* Destroy all pages of all lists */
-       for (p = DLIST_TOP(&pool->pages); p != NULL; p = t) {
-               t = DLIST_NEXT(p);
-               (void) pool_page_destroy(p);
-       }
-       for (p = DLIST_TOP(&pool->fpages); p != NULL; p = t) {
-               t = DLIST_NEXT(p);
-               (void) pool_page_destroy(p);
-       }
-       for (p = DLIST_TOP(&pool->epages); p != NULL; p = t) {
-               t = DLIST_NEXT(p);
-               (void) pool_page_destroy(p);
-       }
-
-       /* Invalidate pool_t */
-       pool->magic = 0;
-}
-
-
-/*
- * Allows to very efficiently allocate a single node from the specified pool,
- * optionally initializing it's memory to zeros. Returns the newly allocated
- * node pointer on success, or NULL on error.
- */
-pnode_t *
-pool_alloc(pool_t *pool, int zero)
-{
-       pnode_t                 *pnode = NULL;
-       register bpage_t        *page;
-
-       ASSERT(POOL_VALID(pool));
-       ASSERT(!zero || pool->create == NULL);
-
-       /* Are there any partially used pages? */
-       if ((page = DLIST_TOP(&pool->pages)) == NULL) {
-               /*
-                * No, we thus attempt to move a page from our empty pages
-                * cache back into our usable pages list. The order of the
-                * usable page list becomes irrelevant at DLIST_SWAP() since
-                * it will be the only node.
-                */
-               if ((page = DLIST_TOP(&pool->epages)) == NULL) {
-                       /*
-                        * No more free pages in our cache neither.
-                        * If maxpages is set and not yet reached, we need
-                        * to create a new page.  If we can't, return NULL
-                        * for error.
-                        */
-                       if (pool->maxpages == 0 ||
-                           DLIST_NODES(&pool->fpages) < pool->maxpages) {
-                               if ((page = pool_page_create("pool_alloc",
-                                   pool)) == NULL)
-                                       return NULL;
-                               DLIST_APPEND(&pool->pages, (node_t *)page);
-                       } else
-                              return NULL;
-               } else
-                       DLIST_SWAP(&pool->pages, &pool->epages, (node_t *)page,
-                           0);
-       }
-
-       /*
-        * <page> now points to a page we know we can at least get a free
-        * object node from. Obtain one and unlink it.
-        */
-       pnode = DLIST_TOP(&page->objects);
-       DLIST_UNLINK(&page->objects, (node_t *)pnode);
-
-       /*
-        * Have we obtained the last available object from this page?
-        * If so, move the page to the full pages list. The order of the
-        * full pages list nodes is irrelevant, since we don't know which
-        * of those pages are more likely to be swapped to the usable
-        * pages list first, and we won't run through that list, except at
-        * pool_destroy().
-        */
-       if (DLIST_NODES(&page->objects) == 0)
-               DLIST_SWAP(&pool->fpages, &pool->pages, (node_t *)page, 0);
-
-       /*
-        * If requested, zero object. This is stupid if a constructor and
-        * destructor are used, but can be useful otherwise.
-        */
-       if (zero) {
-               page = pnode->page;
-               (void) memset(pnode, 0, pool->nodesize);
-               pnode->page = page;
-       }
-
-       /* Mark this node as a valid allocated object */
-       pnode->magic = MAGIC_PNODE;
-
-       return pnode;
-}
-
-
-/*
- * Efficiently frees the specified node back to the pool it was allocated from.
- * Returns NULL.  Uses heuristics keeping statistics to determine when to
- * actually shrink the memory blocks internally used by the pool, so that
- * frequently growing and shrinking pools will remain large for scalability.
- * This also makes a big difference when constructors and destructors are used
- * and need to execute a significant amount of code.
- */
-pnode_t *
-pool_free(pnode_t *pnode)
-{
-       register bpage_t        *page = pnode->page;
-       register pool_t         *pool = page->pool;
-       register uint32_t       count;
-
-       ASSERT(PNODE_VALID(pnode));
-
-       /* Invalidate object */
-       pnode->magic = 0;
-
-       /*
-        * Record how many nodes there currently are in our page's object
-        * list, to be used later on
-        */
-       count = DLIST_NODES(&page->objects);
-
-       /*
-        * Add node back to it's page's object list.  Insert it so that we
-        * favor reuse of recently used objects soon.
-        */
-       DLIST_INSERT(&page->objects, (node_t *)pnode);
-
-       /*
-        * Was this page full before we inserted our node?  If so, page is in
-        * full pages list.  Move it to the usable pages list.  Insert it to
-        * favor reuse of recently used pages soon (this page will soon return
-        * back to the full pages list).
-        */
-       if (count == 0)
-               DLIST_SWAP(&pool->pages, &pool->fpages, (node_t *)page, 1);
-       else {
-               /*
-                * Did we cause our node insertion to totally free back the
-                * page?  If so, the page is on the usable free list, but move
-                * it back to the empty pages list.  Insert it to favor reuse
-                * of recently used pages soon (this page will be the first to
-                * get used again when the usable pages list needs pages).
-                */
-               if (++count == pool->nodesperpage) {
-                       DLIST_SWAP(&pool->epages, &pool->pages, (node_t *)page,
-                           1);
-               }
-       }
-
-       if ((pool->minpages < pool->maxpages) ||
-           (pool->minpages == 0 && pool->maxpages == 0)) {
-               register int    exceeding;
-
-               /*
-                * This pool_t is allowed to shrink.  Maintain average pages
-                * usage to prevent destroying our pages in the empty pages
-                * list unless we should.
-                */
-               count = DLIST_NODES(&pool->pages) + DLIST_NODES(&pool->fpages);
-               pool->avgtotal += count;
-               pool->avgcnt++;
-
-               /*
-                * Using * 8 here means that pool_free() needs to at least be
-                * called to release as much objects as can fit into eight full
-                * pages in order to execute the following block.  But of
-                * course, this does not mean that eight pages will recently
-                * have been freed, since allocations probably also occured
-                * meanwhile.
-                */
-               if (pool->avgcnt > pool->nodesperpage * 8) {
-                       /*
-                        * Do statistics suggest that we should shrink the
-                        * pool?  If so, free pages from our empty pages
-                        * cache back to the system, destroying their objects
-                        * if necessary.  We'll make sure to at least leave a
-                        * one page hysterisis for better performance.
-                        */
-                       if ((exceeding = (count + DLIST_NODES(&pool->epages)
-                           - 1) - (pool->avgtotal / pool->avgcnt)) > 0) {
-                               register list_t *epages = &pool->epages;
-
-                               /*
-                                * Preferably free pages which haven't been
-                                * used recently.
-                                */
-                               for (; exceeding > 0 &&
-                                    (page = DLIST_BOTTOM(epages)) != NULL;
-                                    exceeding--) {
-                                       DLIST_UNLINK(epages, (node_t *)page);
-                                       (void) pool_page_destroy(page);
-                               }
-                       }
-                       /* Reset statistics */
-                       pool->avgcnt = 1;
-                       pool->avgtotal = count;
-               }
-       }
-
-       return NULL;
-}
diff --git a/tests/sdl-client/pool.h b/tests/sdl-client/pool.h
deleted file mode 100644 (file)
index f132c3c..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/* $Id: pool.h,v 1.1 2006/04/27 10:59:19 mmondor Exp $ */
-
-/*
- * Copyright (C) 2001-2006, Matthew Mondor
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Matthew Mondor.
- * 4. The name of Matthew Mondor may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- * 5. Redistribution of source code may not be released under the terms of
- *    any GNU Public License derivate.
- *
- * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-
-
-#ifndef MPOOL_H
-#define MPOOL_H
-
-
-
-#include <stdint.h>
-
-#include <dlist.h>
-
-
-
-/* Useful to o-align a value relative to v (sizes and pointers) */
-#define OALIGN_CEIL(v, o) \
-    ((((size_t)(v)) + (sizeof(o)) - 1) / (sizeof(o)) * (sizeof(o)))
-#define OALIGN_FLOOR(v, o)     ((size_t)(v) - (((size_t)(v) % sizeof(o))))
-
-/* Useful to byte align a value with supplied size */
-#define BALIGN_CEIL(v, s)      ((((size_t)(v)) + (s) - 1) / (s) * (s))
-#define BALIGN_FLOOR(v, s)     ((size_t)(v) - (((size_t)(v) % (s))))
-
-
-
-typedef struct pnode   pnode_t;
-typedef struct bpage   bpage_t;
-typedef struct pool    pool_t;
-
-
-
-#define MAGIC_POOL     0x504f4f4c      /* POOL */
-#define MAGIC_PAGE     0x50414745      /* PAGE */
-#define MAGIC_PNODE    0x504e4f44      /* PNOD */
-
-#define POOL_VALID(p)  ((p) != NULL && (p)->magic == MAGIC_POOL)
-#define PNODE_VALID(p) ((p) != NULL && (p)->magic == MAGIC_PNODE && \
-       (p)->page != NULL && (p)->page->magic == MAGIC_PAGE && \
-       (p)->page->pool != NULL && (p)->page->pool->magic == MAGIC_POOL)
-
-
-
-/* Header structure of internally allocated/prepared page/blocks */
-struct bpage {
-    node_t             node;
-    uint32_t           magic;
-    pool_t             *pool;
-    list_t             objects;
-};
-
-/* Header structure of individual pool objects */
-struct pnode {
-    node_t             node;
-    uint32_t           magic;
-    bpage_t            *page;
-};
-
-/* Pool control structure */
-struct pool {
-    pnode_t            node;   /* Hey, we never know, a pool_t of pool_t */
-    uint32_t           magic;
-    const char         *label;
-    void               *(*malloc)(size_t);
-    void               (*free)(void *);
-    int                        (*create)(pnode_t *);
-    void               (*destroy)(pnode_t *);
-    size_t             nodesize, pagesize;
-    uint32_t           minpages, maxpages, nodesperpage;
-    uint32_t           avgtotal, avgcnt;
-    /* Usable pages, totally full/busy pages, totally empty/free pages */
-    list_t             pages, fpages, epages;
-};
-
-
-
-/* Public API prototypes */
-extern int             pool_init(pool_t *, const char *, void *(*)(size_t),
-                           void (*)(void *), int (*)(pnode_t *),
-                           void (*)(pnode_t *), size_t,
-                           uint32_t, uint32_t, uint32_t);
-extern void            pool_destroy(pool_t *);
-extern pnode_t *       pool_alloc(pool_t *, int);
-extern pnode_t *       pool_free(pnode_t *);
-
-
-
-#endif
diff --git a/tests/sdl-client/rawobjs.h b/tests/sdl-client/rawobjs.h
deleted file mode 100644 (file)
index 89d59bc..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/* $Id: rawobjs.h,v 1.4 2006/05/10 00:48:40 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/* XXX This file should probably be auto-generated */
-
-
-
-#ifndef RAWOBJS_H
-#define RAWOBJS_H
-
-
-
-/*
- * On win32, binary objects must be referenced without the underscore prefix.
- * Let's then define a few aliases.
- */
-#ifdef WIN32
-
-#define _binary_bmp_FedCA_bmp_enc_size binary_bmp_FedCA_bmp_enc_size
-#define _binary_bmp_FedCA_bmp_enc_start        binary_bmp_FedCA_bmp_enc_start
-#define _binary_bmp_RomDD_bmp_enc_size binary_bmp_RomDD_bmp_enc_size
-#define _binary_bmp_RomDD_bmp_enc_start        binary_bmp_RomDD_bmp_enc_start
-
-#define _binary_wav_nt_cloaked_wav_enc_size binary_wav_nt_cloaked_wav_enc_size  
-#define _binary_wav_nt_cloaked_wav_enc_start binary_wav_nt_cloaked_wav_enc_start
-#define _binary_wav_nt_explosion_other_wav_enc_size binary_wav_nt_explosion_other_wav_enc_size
-#define _binary_wav_nt_explosion_other_wav_enc_start binary_wav_nt_explosion_other_wav_enc_start
-#define _binary_wav_nt_fire_torp_other_wav_enc_size binary_wav_nt_fire_torp_other_wav_enc_size
-#define _binary_wav_nt_fire_torp_other_wav_enc_start binary_wav_nt_fire_torp_other_wav_enc_start
-#define _binary_wav_nt_plasma_hit_wav_enc_size binary_wav_nt_plasma_hit_wav_enc_size
-#define _binary_wav_nt_plasma_hit_wav_enc_start binary_wav_nt_plasma_hit_wav_enc_start
-#define _binary_wav_nt_shield_down_wav_enc_size binary_wav_nt_shield_down_wav_enc_size
-#define _binary_wav_nt_shield_down_wav_enc_start binary_wav_nt_shield_down_wav_enc_start
-#define _binary_wav_nt_shield_up_wav_enc_size binary_wav_nt_shield_up_wav_enc_size
-#define _binary_wav_nt_shield_up_wav_enc_start binary_wav_nt_shield_up_wav_enc_start
-#define _binary_wav_nt_uncloak_wav_enc_size binary_wav_nt_uncloak_wav_enc_size
-#define _binary_wav_nt_uncloak_wav_enc_start binary_wav_nt_uncloak_wav_enc_start
-
-#define _binary_fnt_7x13_fnt_enc_start binary_fnt_7x13_fnt_enc_start
-#define _binary_fnt_7x13_fnt_enc_size  binary_fnt_7x13_fnt_enc_size
-
-#endif
-
-
-
-/*
- * And export symbols to other modules
- */
-
-extern void    *_binary_bmp_FedCA_bmp_enc_size;
-extern void    *_binary_bmp_FedCA_bmp_enc_start;
-extern void    *_binary_bmp_RomDD_bmp_enc_size;
-extern void    *_binary_bmp_RomDD_bmp_enc_start;
-
-extern void    *_binary_wav_nt_cloaked_wav_enc_size;
-extern void    *_binary_wav_nt_cloaked_wav_enc_start;
-extern void    *_binary_wav_nt_explosion_other_wav_enc_size;
-extern void    *_binary_wav_nt_explosion_other_wav_enc_start;
-extern void    *_binary_wav_nt_fire_torp_other_wav_enc_size;
-extern void    *_binary_wav_nt_fire_torp_other_wav_enc_start;
-extern void    *_binary_wav_nt_plasma_hit_wav_enc_size;
-extern void    *_binary_wav_nt_plasma_hit_wav_enc_start;
-extern void    *_binary_wav_nt_shield_down_wav_enc_size;
-extern void    *_binary_wav_nt_shield_down_wav_enc_start;
-extern void    *_binary_wav_nt_shield_up_wav_enc_size;
-extern void    *_binary_wav_nt_shield_up_wav_enc_start;
-extern void    *_binary_wav_nt_uncloak_wav_enc_size;
-extern void    *_binary_wav_nt_uncloak_wav_enc_start;
-
-extern void    *_binary_fnt_7x13_fnt_enc_start;
-extern void    *_binary_fnt_7x13_fnt_enc_size;
-
-
-
-#endif
diff --git a/tests/sdl-client/screen.c b/tests/sdl-client/screen.c
deleted file mode 100644 (file)
index 4cf25f2..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* $Id: screen.c,v 1.11 2006/05/08 21:05:17 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Display related initialization.
- */
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <SDL.h>
-
-#include <conf.h>
-#include <screen.h>
-
-
-
-#define                SCREEN_WIDTH    1024
-#define                SCREEN_HEIGHT   768
-
-
-
-SDL_Surface    *screen_surface;
-int            screen_width, screen_height;
-SDL_Joystick   *gamepad;
-
-
-
-void
-screen_init(void)
-{
-
-       if (SDL_Init(SDL_INIT_EVERYTHING) == -1) {
-               (void) fprintf(stderr, "main() - SDL_Init() - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-       if ((screen_surface = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32,
-           SDL_DOUBLEBUF | SDL_FULLSCREEN)) == NULL) {
-               (void) fprintf(stderr, "main() - SDL_SetVideoMode() - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-
-       if (SDL_NumJoysticks > 0)
-               gamepad = SDL_JoystickOpen(0);
-
-       screen_width = SCREEN_WIDTH;
-       screen_height = SCREEN_HEIGHT;
-
-       (void) atexit(screen_destroy);
-}
-
-void
-screen_destroy(void)
-{
-
-       SDL_Quit();
-}
diff --git a/tests/sdl-client/screen.h b/tests/sdl-client/screen.h
deleted file mode 100644 (file)
index d98322f..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/* $Id: screen.h,v 1.3 2006/05/08 08:17:00 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Screen related initialization.
- */
-
-
-
-#ifndef SCREEN_H
-#define SCREEN_H
-
-
-
-#include <SDL.h>
-
-
-
-extern SDL_Surface     *screen_surface;
-extern int             screen_width, screen_height;
-extern SDL_Joystick    *gamepad;
-
-
-
-void                   screen_init(void);
-void                   screen_destroy(void);
-
-
-
-#endif
diff --git a/tests/sdl-client/tests/draw.c b/tests/sdl-client/tests/draw.c
deleted file mode 100644 (file)
index da2c393..0000000
+++ /dev/null
@@ -1,948 +0,0 @@
-/* $Id: draw.c,v 1.1 2006/05/03 14:20:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * XXX TODO XXX
- * - Fix most all code using multiplication to locate x,y pixel positions into
- *   the display to use the screen_lines array for optimization.
- *   This however could cause a problem for SDL surfaces other than the screen
- *   which are involved. A possibility to fix this would be to wrap the
- *   SDL_Surface into a custom structure, which could also hold the optimized
- *   line position array for each...
- * - Implement a diff function, to fill a surface with the difference between
- *   two other surfaces... This might be good for some type of effects and
- *   animations. Hmm there possibly would be a problem with the 0 transparent
- *   color though... Consider following situation:
- *   - Diff detects new 0 color pixels in second image, how would we effect
- *     transformation of first image to second one, since we can't blit zero
- *     color images? If we did blit zero color, how would we detect what
- *     pixels consist in the difference? Perhaps that we would need a special
- *     diff format rather than just blitting differences into a zero color
- *     surface. Diff format could be very similar to runlength-style encoding
- *     format, if not the same, perhaps. I would only need to add section
- *     support, other than just compression... I.E. section starting at x,y,
- *     of total length l, followed by runlength compressed section...
- *   Such diffs might also be nice to send over the network when images change
- *   or such...
- * - Implement simple runlength compression and decompression support, with
- *   possibly load/save image support.
- * - Maybe implement simple animation format based on above diff and runlength
- *   support. It would be enough to implement small animated sets with limited
- *   motion.
- * - Implement ellipse and ellipse arc support
- * - Splines support would be great but I would need to read about it.
- *   If really required, SDL_gfx might be worth using.
- * - Once all required primitives have been implemented, allow support for
- *   parallel postscript commands output, so that it would be possible to
- *   print results. This would allow to have consistent on-screen and printer
- *   results (this is not game related, it could be used for applications).
- * * Postscript has all of the above. It actually would be nice if I could
- *   have my application draw postscript in real time while internally keeping
- *   the necessary information in memory of the screen state to be able to
- *   also print to a postscript printer. It seems that ghostscript has a
- *   graphics library. Can it be used by a third party application easily?
- *   Also, if I used postscript, how would I allow bitmap images to be
- *   supported? Especially as the relative scaling of everything would have
- *   to be respected?
- *   - It also would be possible to simply use X11R6. However, this would
- *     limit client applications to run on unix systems in most cases.
- *     Moreover, I probably would still require some kind of hack to
- *     internally keep track of postscript equivalents for printing, or the
- *     contrary, to process using postscript and draw using X11, etc...
- *     I of course still would need to provide my own toolkit.
- *   - The main problem I would have with both above techniques is dealing
- *     with fonts. Obviously, fonts would need to be vectorial, and in a way
- *     which is useful for postscript output. I would need to have an onscreen
- *     WYSIWYG renderer for the same type of fonts. X11 can supposedly output
- *     GS fonts to screen, using the X Font Server (XFS)... But this requires
- *     clients to have a special configuration, once more.
- *     NOTE: This is fixed, SDL_ttf can be used.
- *   - It would be possible to use bitmap fonts, as long as they are of the
- *     right size to be equivalent to the postscript output, and that the
- *     screen has proper visual to represent the page... If we support
- *     proportional fonts, some new code would need to be added. Moreover, we
- *     probably would not want the proportional fonts to be used where the
- *     user types text, to ease the editor's tasks... We would need to at
- *     least support fixed/courrier, times and helvetica. We would need a font
- *     format which can specify the size of each character of proportional
- *     fonts. Maybe an aditionnal data file along with the bitmap file...
- */
-
-
-
-/* HEADERFILES */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <math.h>
-
-#include <SDL.h>
-
-#include <draw.h>
-#include <conf.h>
-#include <screen.h>
-
-
-
-/* DEFINITIONS */
-
-#ifdef ANTIALIASING    /* conf.h */
-#define DRAW_PIXEL     draw_pixel_antialias
-#else
-#define DRAW_PIXEL     draw_pixel
-#endif
-
-
-
-/* STATIC FUNCTIONS PROTOTYPES */
-
-
-
-/* GLOBALS */
-
-static draw_point_t    *stack_start, *stack_pos, pen;
-static double          sin_table[1000], cos_table[1000];
-static uint32_t                **screen_lines;
-
-
-
-/* PRIVATE FUNCTIONS */
-
-
-
-/* PUBLIC FUNCTIONS */
-
-int
-draw_init(void)
-{
-
-       /* Allocate memory for draw_fill_*() stack */
-       if ((stack_start = malloc(sizeof(draw_point_t) *
-           (screen_width * screen_height) * 4)) == NULL)
-               return -1;
-
-       /*
-        * Allocate and initialize fast screen display line index lookup table,
-        * which can be used by pixel drawing routines without the need for
-        * multiplications.
-        */
-       {
-               uint32_t        *lptr;
-               int             i;
-
-               if ((screen_lines = malloc(sizeof(uint32_t *) *
-                   screen_height)) == NULL)
-                       return -1;
-
-               for (lptr = (uint32_t *)(screen_surface->pixels), i = 0;
-                    i < screen_height; i++, lptr += screen_width)
-                       screen_lines[i] = lptr;
-       }
-
-       /*
-        * Initialize our sin/cos trigonometric functions arrays for
-        * performance when mesuring rotations in radians.
-        * XXX We should add pixel ratio modifyer too here.
-        */
-       {
-               int     i;
-               double  f;
-
-               for (i = 0; i < 1000; i++) {
-                       f = ((2 * M_PI) / 1000) * (i - 250);
-                       sin_table[i] = sin(f);
-                       cos_table[i] = cos(f);
-               }
-       }
-
-       return 0;
-}
-
-/* The following functions require that screen_surface be locked. */
-
-/* Draws a vertical line at specified position and of specified height */
-inline void
-draw_vline(draw_point_t *p, int height, uint32_t col)
-{
-       register uint32_t       *ptr;
-       register int            i;
-
-       assert(p != NULL);
-       assert(!(p->x < 0 || p->x >= screen_width ||
-           p->y < 0 || p->y + height > screen_height));
-
-       /* XXX Should use lines array */
-       for (ptr = &((uint32_t *)screen_surface->pixels)[
-           (p->y * screen_width) + p->x], i = height; i > 0;
-           i--, ptr = &ptr[screen_width])
-               *ptr = col;
-}
-
-/* Draws an horizontal line at specified position and of specified width */
-inline void
-draw_hline(draw_point_t *p, int width, uint32_t col)
-{
-       register uint32_t       *ptr, *tptr;
-
-       assert(p != NULL);
-       assert(!(p->x < 0 || p->x + width > screen_width ||
-           p->y < 0 || p->y >= screen_height));
-
-       /* XXX Should use lines array */
-       for (ptr = &((uint32_t *)screen_surface->pixels)[
-           (p->y * screen_width + p->x)], tptr = &ptr[width]; ptr < tptr; )
-               *ptr++ = col;
-}
-
-/*
- * Draws a rectangle of specified colors. Two colors can be specified for a
- * special 3d-like effect (although both can be the same if wanted).
- */
-inline void
-draw_rect(draw_rect_t *r, uint32_t hicol, uint32_t locol)
-{
-       draw_point_t    p;
-
-       assert(r != NULL);
-       assert(!(r->x < 0 || r->x + r->w > screen_width ||
-           r->y < 0 || r->y + r->h > screen_height));
-
-       p.x = r->x;
-       p.y = r->y;
-       draw_hline(&p, r->w, hicol);
-       p.y++;
-       draw_vline(&p, r->h - 1, hicol);
-       p.x = r->x + r->w - 1;
-       p.y--;
-       draw_vline(&p, r->h, locol);
-       p.x = r->x + 1;
-       p.y = r->y + r->h - 1;
-       draw_hline(&p, r->w - 1, locol);
-}
-
-/*
- * Draws rectangular box at (x,y) to (x+w-1,y+h-1), using lcol for the 3d
- * border light color, dcol for 3d border dark color, filled with fcol (or 0
- * for transparent interior) and of specified 3d depth.
- */
-void
-draw_rect_3d(draw_rect_t *r, uint32_t hicol, uint32_t locol, uint32_t fillcol,
-    int depth)
-{
-       draw_rect_t     rect;
-
-       assert(r != NULL);
-       assert(!(r->x < 0 || r->x + r->w > screen_width ||
-           r->y < 0 || r->y + r->h > screen_height));
-
-       if (fillcol != 0) {
-               rect.x = r->x + 1;
-               rect.y = r->y + 1;
-               rect.w = r->w - 2;
-               rect.h = r->h - 2;
-               draw_rect_fill(&rect, fillcol);
-       }
-       rect = *r;
-       for (; depth > 0; depth--, rect.x += 1, rect.y += 1,
-            rect.w -= 2, rect.h -= 2)
-               draw_rect(&rect, hicol, locol);
-}
-
-/* Allows to fill specified rectangle with specified color */
-inline void
-draw_rect_fill(draw_rect_t *r, uint32_t col)
-{
-       register uint32_t       *ptr, *tptr = NULL, *lptr;
-
-       assert(r != NULL);
-       assert(!(r->x < 0 || r->x + r->w > screen_width ||
-           r->y < 0 || r->y + r->h > screen_height));
-
-       if (r->w == screen_width) {
-               /*
-                * Even better optimization, setting an entire single block of
-                * multiple lines together.
-                * XXX Should use lines array
-                */
-               for (ptr = &((uint32_t *)screen_surface->pixels)[
-                   (r->y * screen_width) + r->x],
-                   tptr = &ptr[screen_width * r->h];
-                   ptr < tptr; )
-                       *ptr++ = col;
-       } else {
-               /* Use line-based optimizations */
-               /* XXX Should use lines array */
-               for (ptr = &((uint32_t *)screen_surface->pixels)[
-                   (r->y * screen_width) + r->x],
-                   tptr = &((uint32_t *)screen_surface->pixels)[
-                   ((r->y + r->h - 1) * screen_width) + (r->x + r->w)];
-                   ptr < tptr; ptr = &ptr[screen_width - r->w]) {
-                       for (lptr = &ptr[r->w]; ptr < lptr; )
-                               *ptr++ = col;
-               }
-       }
-}
-
-/*
- * Similar to draw_rect_fill(), but causes pixels to be XORed against m,
- * to toggle their bits. This is reversable by another call to this function
- * on the same area again. This can be useful for the implementation of a
- * block cursor. However, because of the disposition of the current 256 color
- * palette, the effect might not be what is expected (some colors will render
- * too bright or too dark to be considered an inversing effect).
- */
-void
-draw_rect_fill_xor(draw_rect_t *r, uint32_t mask)
-{
-       register uint32_t       *ptr, *toptr, *lptr;
-
-       assert(r != NULL);
-       assert(!(r->x < 0 || r->x + r->w > screen_width ||
-           r->y < 0 || r->y + r->h > screen_height));
-
-       /* XXX Should use lines array */
-       for (ptr = &((uint32_t *)screen_surface->pixels)[
-           (r->y * screen_width) + r->x],
-           toptr = &((uint32_t *)screen_surface->pixels)[
-           ((r->y + r->h - 1) * screen_width) + (r->x + r->w)];
-           ptr < toptr; ptr = &ptr[screen_width - r->w]) {
-               for (lptr = &ptr[r->w]; ptr < lptr; )
-                       *ptr++ ^= mask;
-       }
-}
-
-/*
- * Similar to draw_rect_fill(), but causes pixels which are not of the bgcol
- * to be reversed to the bgcol. Other pixels, which already were of bgcol are
- * set to col. This function is useful for the implementation of a block
- * cursor.
- */
-void
-draw_rect_fill_inverse(draw_rect_t *r, uint32_t col, uint32_t bgcol)
-{
-       register uint32_t       *ptr, *toptr, *lptr;
-
-       assert(r != NULL);
-       assert(!(r->x < 0 || r->x + r->w > screen_width ||
-           r->y < 0 || r->y + r->h > screen_height));
-
-       /* XXX Should use lines array */
-       for (ptr = &((uint32_t *)screen_surface->pixels)[
-           (r->y * screen_width) + r->x],
-           toptr = &((uint32_t *)screen_surface->pixels)[
-           ((r->y + r->h - 1) * screen_width) + (r->x + r->w)];
-           ptr < toptr; ptr = &ptr[screen_width - r->w]) {
-               for (lptr = &ptr[r->w]; ptr < lptr; ptr++)
-                       *ptr = (*ptr == bgcol ? col : bgcol);
-       }
-}
-
-/*
- * Very similar to draw_rect_fill(), but causes empty/transparent pixels to be
- * left at 50%. Can be used to simulate transparency without the need for
- * alpha values. Especially useful with restricted palettes, or simply to
- * create an effect.
- */
-void
-draw_rect_fill_transparent(draw_rect_t *r, uint32_t col)
-{
-       register uint32_t       *ptr, *toptr, *lptr;
-       int                     even;
-
-       assert(r != NULL);
-       assert(!(r->x < 0 || r->x + r->w > screen_width ||
-           r->y < 0 || r->y + r->h > screen_height));
-
-       /* XXX Should use lines array */
-       for (ptr = &((uint32_t *)screen_surface->pixels)[
-           (r->y * screen_width) + r->x],
-           toptr = &((uint32_t *)screen_surface->pixels)[
-           ((r->y + r->h - 1) * screen_width) + (r->x + r->w)], even = 0;
-           ptr < toptr;
-           ptr = &ptr[screen_width - r->w], even = (even == 0 ? 1 : 0)) {
-               ptr += even;
-               for (lptr = &ptr[r->w]; ptr < lptr; ptr += 2)
-                       *ptr = col;
-               ptr -= even;
-       }
-}
-
-/*
- * Similar to SDL_BlitSurface(), but less efficient, it allows to blit the
- * specified image in one color. All non-zero pixels are copied, while others
- * are output as fg. In the case where bg is non-zero, zero pixels output bg.
- * The screen surface should be locked when calling this function.
- */
-void
-draw_surface_color(SDL_Surface *surface, draw_rect_t *r, draw_point_t *p,
-    uint32_t fg, uint32_t bg)
-{
-       register uint32_t       *dstptr, *tdstptr, *srcptr, *tptr;
-
-       assert(surface != NULL);
-       assert(r != NULL);
-       assert(p != NULL);
-       assert(!(r->x < 0 || r->x + r->w > surface->w ||
-           r->y < 0 || r->y + r->h > surface->h));
-       assert(!(p->x < 0 || p->x + r->w > surface->w));
-
-       /*
-        * For performance we want to avoid having to include the bg color
-        * check every loop iteration. We prefer to have two loops instead.
-        * Moreover, we optimize the loop as such to avoid multiplications
-        * and divisions, using a line-based algorithm with additions only.
-        */
-       if (bg == 0) {
-               /* XXX Should use lines array */
-               for (dstptr = &((uint32_t *)screen_surface->pixels)[
-                   (p->y * screen_width) + p->x],
-                   tdstptr = &((uint32_t *)screen_surface->pixels)[
-                   ((p->y + r->h - 1) * screen_width) + (p->x + r->w)],
-                   srcptr = &((uint32_t *)surface->pixels)[
-                   (r->y * surface->w) + r->x];
-                   dstptr < tdstptr;
-                   dstptr = &dstptr[screen_width - r->w],
-                   srcptr = &srcptr[surface->w - r->w]) {
-                       for (tptr = &dstptr[r->w]; dstptr < tptr;
-                           dstptr++, srcptr++) {
-                               if ((*srcptr & 0xff000000) != 0)
-                                       *dstptr = fg;
-                       }
-               }
-       } else {
-               /* XXX Should use lines array */
-               for (dstptr = &((uint32_t *)screen_surface->pixels)[
-                   (p->y * screen_width) + p->x],
-                   tdstptr = &((uint32_t *)screen_surface->pixels)[
-                   ((p->y + r->h - 1) * screen_width) + (p->x + r->w)],
-                   srcptr = &((uint32_t *)surface->pixels)[
-                   (r->y * surface->w) + r->x];
-                   dstptr < tdstptr;
-                   dstptr = &dstptr[screen_width - r->w],
-                   srcptr = &srcptr[surface->w - r->w]) {
-                       for (tptr = &dstptr[r->w]; dstptr < tptr; )
-                               *dstptr++ = ((*srcptr++ & 0xff000000) == 0 ?
-                                   bg : fg);
-               }
-       }
-}
-
-void
-draw_surface_color_antialias(SDL_Surface *surface, draw_rect_t *r,
-    draw_point_t *p, uint32_t fg, uint32_t bg)
-{
-       register uint32_t       *srcptr, *tsrcptr, *tptr;
-       register int            x, y;
-
-       assert(surface != NULL);
-       assert(r != NULL);
-       assert(p != NULL);
-       assert(!(r->x < 0 || r->x + r->w > surface->w ||
-           r->y < 0 || r->y + r->h > surface->h));
-       assert(!(p->x < 0 || p->x + r->w > screen_width ||
-           p->y < 0 || p->y + r->h > screen_height));
-
-       /* XXX Should use lines array */
-       for (tsrcptr = &((uint32_t *)surface->pixels)[
-           ((r->y + r->h - 1) * surface->w) + (r->x + r->w)],
-           srcptr = &((uint32_t *)surface->pixels)[
-           (r->y * surface->w) + r->x],
-           y = p->y;
-           srcptr < tsrcptr;
-           srcptr = &srcptr[surface->w - r->w], y++) {
-               for (x = p->x, tptr = &srcptr[r->w]; srcptr < tptr;
-                   srcptr++, x++) {
-                       if (bg == 0) {
-                               if ((*srcptr & 0xff000000) != 0)
-                                       draw_pixel_antialias(x, y, fg);
-                       } else
-                               draw_pixel_antialias(x, y,
-                                   ((*srcptr & 0xff000000) == 0 ? bg : fg));
-               }
-       }
-}
-
-/*
- * Similar to SDL_BlitSurface(), but less efficient, it allows to blit a
- * perfect copy of a surface area to another surface area. This is most useful
- * when colors have been setup as transparent and that an opaque identical
- * copy is wanted.
- */
-void
-draw_surface_copy(SDL_Surface *dstsurface, draw_point_t *p,
-    SDL_Surface *srcsurface, draw_rect_t *r)
-{
-       uint32_t        *dstptr, *tdstptr, *srcptr, *tptr;
-
-       assert(dstsurface != NULL);
-       assert(p != NULL);
-       assert(srcsurface != NULL);
-       assert(r != NULL);
-       assert(!(r->x < 0 || r->x + r->w > srcsurface->w ||
-           r->y < 0 || r->y + r->h > srcsurface->h));
-       assert(!(p->x < 0 || p->x + r->w > dstsurface->w ||
-           p->y < 0 || p->y + r->h > dstsurface->h));
-
-       /* XXX Should use lines array */
-       for (dstptr = &((uint32_t *)dstsurface->pixels)[
-           (p->y * dstsurface->w) + p->x],
-           tdstptr = &((uint32_t *)dstsurface->pixels)[
-           ((p->y + r->h - 1) * dstsurface->w) + (p->x + r->w)],
-           srcptr = &((uint32_t *)srcsurface->pixels)[
-           (r->y * srcsurface->w) + r->x];
-           dstptr < tdstptr;
-           dstptr = &dstptr[dstsurface->w - r->w],
-           srcptr = &srcptr[srcsurface->w - r->w]) {
-               for (tptr = &dstptr[r->w]; dstptr < tptr; )
-                       *dstptr++ = *srcptr++;
-       }
-}
-
-/*
- * Blits a single pixel of specified color to screen at specified position.
- * Note that this function does not consider color 0 to be transparent.
- * This function, by exception, does not require the use of a draw_point_t.
- * This allows to use register based optimizations in functions calling us
- * (They do not need to keep counters in a memory structure when looping).
- */
-inline void
-draw_pixel(int x, int y, uint32_t col)
-{
-
-       /*
-        * Instead of using this alternative, which requires multiplication:
-        * ((uint32_t *)screen_surface->pixels)[(y * screen_width) + x] = col;
-        * Use the advantage of our screen_lines array for indexing
-        * optimization.
-        */
-       screen_lines[y][x] = col;
-}
-
-inline void
-draw_pixel_transparent(int x, int y, uint32_t col, int alpha)
-{
-       uint32_t        ccol;
-
-       /* This condition can happen because we are called for antialiasing */
-       if (x >= screen_width || x < 0 || y >= screen_height || y < 0)
-               return;
-
-       alpha &= 0xff;
-
-       /* First optimize possible cases */
-       if (alpha == 0x00)
-               return;
-       if (alpha == 0xff) {
-               draw_pixel(x, y, col);
-               return;
-       }
-
-       /* Transparently blit pixel if necessary */
-       if ((ccol = draw_getpixel2(x, y)) != col) {
-               int     r, g, b, nr, ng, nb;
-
-               /*
-                * Decompose into r, g, b levels, first current screen pixel
-                * color
-                */
-               r = ((ccol & 0x00ff0000) >> 16);
-               g = ((ccol & 0x0000ff00) >> 8);
-               b = (ccol & 0x000000ff);
-               /* Then supplied color */
-               nr = ((col & 0x00ff0000) >> 16);
-               ng = ((col & 0x0000ff00) >> 8);
-               nb = (col & 0x000000ff);
-
-               /*
-                * Apply opacity modification on supplied color according to
-                * alpha
-                */
-               nr = nr * alpha / 0xff;
-               ng = ng * alpha / 0xff;
-               nb = nb * alpha / 0xff;
-
-               /*
-                * XXX bug here! Works fine when blitting lighter colors on
-                * darker ones, but not for dark colors over brighter
-                * background.  I probably need something as simple as reverse
-                * proportional function or such...
-                */
-               /* Mix supplied color with pixel color */
-               if ((r = (r + nr) / 2) > 0xff)
-                       r = 0xff;
-               if ((g = (g + ng) / 2) > 0xff)
-                       g = 0xff;
-               if ((b = (b + nb) / 2) > 0xff)
-                       b = 0xff;
-
-               /* Recompose into a 32-bit color */
-               ccol = (((r << 16) & 0x00ff0000) | ((g << 8) & 0x0000ff00) |
-                   (b & 0x000000ff));
-
-               /* Finally blit resulting pixel back to screen */
-               draw_pixel(x, y, ccol);
-       }
-}
-
-/*
- * XXX Test.
- */
-inline void
-draw_pixel_antialias(int x, int y, uint32_t col)
-{
-#define AA_T   0xd0    /*0x60*/
-
-       assert(!(x >= screen_width || x < 0 || y >= screen_height || y < 0));
-
-       draw_pixel(x, y, col);
-       draw_pixel_transparent(x, y - 1, col, AA_T);
-       draw_pixel_transparent(x + 1, y, col, AA_T);
-       draw_pixel_transparent(x, y + 1, col, AA_T);
-       draw_pixel_transparent(x - 1, y, col, AA_T);
-
-#undef AA_T
-}
-
-/* Returns the color of pixel at specified location on screen. */
-inline uint32_t
-draw_getpixel(draw_point_t *p)
-{
-
-       assert(p != NULL);
-
-       return screen_lines[p->y][p->x];
-}
-
-inline uint32_t
-draw_getpixel2(int x, int y)
-{
-
-       return screen_lines[y][x];
-}
-
-/*
- * Blits a line on screen of specified color (x,y)->(x2,y2). Note that color 0
- * is not considered transparent. Probably does not use the best algorithm,
- * but SDL doesn't provide hardware line blitting support, and I at least
- * needed such a function... This seems to be fast enough, using this
- * home-rolled algorithm for now.
- */
-/* XXX Modify so that it performs a gradient using draw_pixel_transparent()
- * with various alpha values when lines are nor vertical, horizontal or
- * diagonal. I.E.
- * --++--
- *       --++--
- * This is apparently a known antialiasing algorithm for lines and would
- * probably be faster than using my current method.
- */
-void
-draw_line(draw_point_t *p1, draw_point_t *p2, uint32_t col)
-{
-       int             ix, iy;
-       register int    x, y, tx, ty;
-       double          f, fa;
-
-       assert(p1 != NULL);
-       assert(p2 != NULL);
-       assert(!(p1->x < 0 || p1->x >= screen_width ||
-           p1->y < 0 || p1->y >= screen_height));
-       assert(!(p2->x < 0 || p2->x >= screen_width ||
-           p2->y < 0 || p2->y >= screen_height));
-
-       /*
-        * Convert quadrant 1 to 3, and quadrant 2 to 4. This ensures that we
-        * only need to blit the line from top to bottom.
-        */
-       if (p1->y > p2->y) {
-               draw_point_t    *p;
-
-               p = p1;
-               p1 = p2;
-               p2 = p;
-       }
-
-       /* Test for cases which can easily be optimized */
-       if (p1->x == p2->x) {
-               if (p1->y == p2->y) {
-                       /* Only a single pixel to blit */
-                       draw_pixel(p1->x, p1->y, col);
-                       return;
-               }
-               /* We can use draw_vline() */
-               draw_vline(p1, (p2->y - p1->y), col);
-               return;
-       }
-       if (p1->y == p2->y) {
-               /* We can use draw_hline() */
-               if (p1->x < p2->x)
-                       draw_hline(p1, (p2->x - p1->x), col);
-               else
-                       draw_hline(p2, (p1->x - p2->x), col);
-               return;
-       }
-
-       if (p1->x < p2->x) {
-               /* Left to right blitting, quadrant 4 */
-
-               /* Obtain width/height ratio */
-               ix = p2->x - p1->x;
-               iy = p2->y - p1->y;
-               if (ix == iy) {
-                       /*
-                        * Equal ratio, no need to use floating point
-                        * arithmetic
-                        */
-                       for (x = p1->x, y = p1->y, tx = p2->x, ty = p2->y;
-                           x <= tx && y <= ty; x++, y++)
-                               DRAW_PIXEL(x, y, col);
-               } else if (ix > iy) {
-                       /*
-                        * XXX Use tf double instead of converting f to int
-                        * in comparision and test if speed is gained
-                        */
-                       /* X ratio larger, use floating point for Y count */
-                       for (fa = (double)iy / (double)ix,
-                           f = (double)p1->y, x = p1->x, tx = p2->x;
-                           (int)f <= p2->y && x <= tx; x++, f += fa)
-                               DRAW_PIXEL(x, (int)f, col);
-               } else {
-                       /* Y ratio larger, use floating point for X count */
-                       for (fa = (double)ix / (double)iy,
-                           f = (double)p1->x, y = p1->y, ty = p2->y;
-                           (int)f <= p2->x && y <= ty; y++, f += fa)
-                               DRAW_PIXEL((int)f, y, col);
-               }
-       } else {
-               /* Right to left blitting, quadrant 3 */
-
-               /* Obtain width/height ratio */
-               ix = p1->x - p2->x;
-               iy = p2->y - p1->y;
-               if (ix == iy) {
-                       /*
-                        * Equal ratio, no need to use floating point
-                        * arithmetic
-                        */
-                       for (x = p1->x, y = p1->y, tx = p2->x, ty = p2->y;
-                           x >= tx && y <= ty; x--, y++)
-                               DRAW_PIXEL(x, y, col);
-               } else if (ix > iy) {
-                       /* X ratio larger, use floating point for Y count */
-                       for (fa = (double)iy / (double)ix,
-                           f = (double)p1->y, x = p1->x, tx = p2->x;
-                           (int)f <= p2->y && x >= tx; x--, f += fa)
-                               DRAW_PIXEL(x, (int)f, col);
-               } else {
-                       /* Y ratio larger, use floating point for X count */
-                       for (fa = (double)ix / (double)iy,
-                           f = (double)p1->x, y = p1->y, ty = p2->y;
-                           (int)f >= p2->x && y <= ty; y++, f -= fa)
-                               DRAW_PIXEL((int)f, y, col);
-               }
-       }
-}
-
-inline void
-draw_moveto(draw_point_t *p)
-{
-
-       assert(p != NULL);
-       assert(!(p->x < 0 || p->x >= screen_width ||
-           p->y < 0 || p->y >= screen_height));
-
-       pen = *p;
-}
-
-inline void
-draw_lineto(draw_point_t *p, uint32_t col)
-{
-
-       assert(p != NULL);
-       assert(!(p->x < 0 || p->x >= screen_width ||
-           p->y < 0 || p->y >= screen_height));
-
-       draw_line(&pen, p, col);
-       pen = *p;
-}
-
-/*
- * Fills the specified region, as long as pixels are bgcol, in all directions.
- * This implementation uses a custom stack with iteration to avoid overflowing
- * the stack. SDL can internally be compiled against various threading
- * libraries, several of which have a fixed stack size (I.E. Pth). Thus,
- * filling rather large areas crashes using the previous implementation.
- * With this one, we don't need to worry about stack room, since we are using
- * the process heap instead. It however may be slower on some architectures
- * than implementations using the actual stack.
- */
-void
-draw_fill_bg(draw_point_t *p, uint32_t col, uint32_t bgcol)
-{
-       draw_point_t    node;
-
-       assert(p != NULL);
-       assert(!(p->x < 0 || p->x >= screen_width ||
-           p->y < 0 || p->y >= screen_height));
-
-       stack_pos = stack_start;
-       *stack_pos++ = *p;
-
-       while (stack_pos > stack_start) {
-               node = *--stack_pos;
-               if (!(node.x < 0 || node.y > screen_width - 1 ||
-                   node.y < 0 || node.y > screen_height - 1)) {
-                       if (draw_getpixel(&node) == bgcol) {
-                               draw_pixel(node.x, node.y, col);
-                               *stack_pos++ =
-                                   (draw_point_t){node.x + 1, node.y};
-                               *stack_pos++ =
-                                   (draw_point_t){node.x, node.y + 1};
-                               *stack_pos++ =
-                                   (draw_point_t){node.x - 1, node.y};
-                               *stack_pos++ =
-                                   (draw_point_t){node.x, node.y - 1};
-                       }
-               }
-       }
-}
-
-/*
- * This implementation varies in that all pixels which are not of specified
- * colors are filled. This is only useful if you know the borders of your
- * surface to fill has the same color. It then allows to perform opaque
- * filling over a variety of colors, contrary to the last function.
- */
-void
-draw_fill_fg(draw_point_t *p, uint32_t col)
-{
-       draw_point_t    node;
-
-       assert(p != NULL);
-       assert(!(p->x < 0 || p->x >= screen_width ||
-           p->y < 0 || p->y >= screen_height));
-
-       stack_pos = stack_start;
-       *stack_pos++ = *p;
-
-       while (stack_pos > stack_start) {
-               node = *--stack_pos;
-               if (!(node.x < 0 || node.y > screen_width - 1 ||
-                   node.y < 0 || node.y > screen_height - 1)) {
-                       if (draw_getpixel(&node) != col) {
-                               draw_pixel(node.x, node.y, col);
-                               *stack_pos++ =
-                                   (draw_point_t){node.x + 1, node.y};
-                               *stack_pos++ =
-                                   (draw_point_t){node.x, node.y + 1};
-                               *stack_pos++ =
-                                  (draw_point_t){node.x - 1, node.y};
-                               *stack_pos++ =
-                                  (draw_point_t){node.x, node.y - 1};
-                       }
-               }
-       }
-}
-
-/*
- * Draws a perfect circle pixel-wise, radius <radius>, expressed in pixels.
- * What it does is draw in four sections, adding pixels at both sides of each
- * section until the sections close the circle.
- */
-void
-draw_circle(draw_point_t *p, int radius, uint32_t col)
-{
-       int     x = 0, y = radius, u = 1, v = 2 * radius - 1, e = 0;
-
-       assert(p != NULL);
-       assert(!(p->x < 0 || p->x + radius > screen_width ||
-               p->y < 0 || p->y + radius > screen_height ||
-               p->x - radius < 0 || p->y - radius < 0));
-
-       while (x < y) {
-               DRAW_PIXEL(p->x + x, p->y + y, col);
-               DRAW_PIXEL(p->x + y, p->y - x, col);
-               DRAW_PIXEL(p->x - x, p->y - y, col);
-               DRAW_PIXEL(p->x - y, p->y + x, col);
-               x++;
-               e += u;
-               u += 2;
-               if (v < (2 * e)) {
-                       y--;
-                       e -= v;
-                       v -= 2;
-               }
-               if (x > y)
-                       break;
-               DRAW_PIXEL(p->x + y, p->y + x, col);
-               DRAW_PIXEL(p->x + x, p->y - y, col);
-               DRAW_PIXEL(p->x - y, p->y - x, col);
-               DRAW_PIXEL(p->x - x, p->y + y, col);
-       }
-}
-
-/*
- * Returns x/y position in (xp,yp), for point at (x,y) of radius <radius> at
- * angle <angle> (in radians). Uses an array suitable for onscreen resolution
- * for efficiency instead of having to always call sin()/cos() functions.
- */
-inline void
-draw_get_vector(draw_point_t *tp, draw_point_t *p, draw_vect_t *v)
-{
-       int     angle;
-
-       assert(tp != NULL);
-       assert(p != NULL);
-       assert(v != NULL);
-       assert(!(p->x < 0 || p->x + v->r > screen_width ||
-           p->y < 0 || p->y + v->r > screen_height ||
-           p->x - v->r < 0 || p->y - v->r < 0));
-
-       if ((angle = v->a) < 0)
-               angle = 1000 - (-angle);
-       else if (angle > 999)
-               angle %= 1000;
-
-       tp->x = (int)(p->x + (cos_table[angle] * v->r));
-       tp->y = (int)(p->y + (sin_table[angle] * v->r));
-}
-
-/*
- * Slower implementation of draw_circle() using floating point, but which
- * can draw arcs.
- */
-void draw_circle_arc(draw_point_t *p, int radius, int a1, int a2, int step,
-    uint32_t col)
-{
-       register int    i;
-       draw_point_t    tp;
-       draw_vect_t     v;
-
-       assert(p != NULL);
-       assert(!(p->x < 0 || p->x + radius > screen_width ||
-           p->y < 0 || p->y + radius > screen_height ||
-           p->x - radius < 0 || p->y - radius < 0));
-
-       if (a2 < a1) {
-               i = a1;
-               a1 = a2;
-               a2 = i;
-       }
-       v.r = radius;
-       v.a = a1;
-       draw_get_vector(&tp, p, &v);
-       draw_moveto(&tp);
-       for (i = a1; i <= a2; i += step) {
-               v.a = i;
-               draw_get_vector(&tp, p, &v);
-               draw_lineto(&tp, col);
-       }
-       if (i > a2) {
-               v.a = a2;
-               draw_get_vector(&tp, p, &v);
-               draw_lineto(&tp, col);
-       }
-}
diff --git a/tests/sdl-client/tests/draw.h b/tests/sdl-client/tests/draw.h
deleted file mode 100644 (file)
index 2cb3647..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* $Id: draw.h,v 1.1 2006/05/03 14:22:06 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-#ifndef DRAW_H
-#define DRAW_H
-
-
-
-#include <stdint.h>
-
-
-
-#define        SCREEN_LOCK()   if (SDL_LockSurface(screen_surface) != 0) \
-                               abort();
-#define SCREEN_UNLOCK()        SDL_UnlockSurface(screen_surface)
-
-
-
-typedef struct draw_point {
-       int     x, y;
-} draw_point_t;
-
-typedef struct draw_vect {
-       int     a, r;
-} draw_vect_t;
-
-typedef struct draw_rect {
-       int     x, y;
-       int     w, h;
-} draw_rect_t;
-
-
-
-extern int             draw_init(void);
-extern inline void     draw_vline(draw_point_t *, int, uint32_t);
-extern inline void     draw_hline(draw_point_t *, int, uint32_t);
-extern inline void     draw_rect(draw_rect_t *, uint32_t, uint32_t);
-extern void            draw_rect_3d(draw_rect_t *, uint32_t, uint32_t,
-                           uint32_t, int);
-extern inline void     draw_rect_fill(draw_rect_t *, uint32_t);
-extern void            draw_rect_fill_xor(draw_rect_t *, uint32_t);
-extern void            draw_rect_fill_inverse(draw_rect_t *, uint32_t,
-                           uint32_t);
-extern void            draw_rect_fill_transparent(draw_rect_t *, uint32_t);
-extern void            draw_surface_color(SDL_Surface *, draw_rect_t *,
-                           draw_point_t *, uint32_t, uint32_t);
-extern void            draw_surface_color_antialias(SDL_Surface *,
-                           draw_rect_t *, draw_point_t *, uint32_t,
-                           uint32_t);
-extern void            draw_surface_copy(SDL_Surface *, draw_point_t *,
-                           SDL_Surface *, draw_rect_t *);
-extern inline void     draw_pixel(int, int, uint32_t);
-extern inline void     draw_pixel_transparent(int, int, uint32_t, int);
-extern inline void     draw_pixel_antialias(int, int, uint32_t);
-extern inline uint32_t draw_getpixel(draw_point_t *);
-extern inline uint32_t draw_getpixel2(int, int);
-extern void            draw_line(draw_point_t *, draw_point_t *, uint32_t);
-extern void            draw_moveto(draw_point_t *);
-extern void            draw_lineto(draw_point_t *, uint32_t);
-extern void            draw_fill_bg(draw_point_t *, uint32_t, uint32_t);
-extern void            draw_fill_fg(draw_point_t *, uint32_t);
-extern void            draw_circle(draw_point_t *, int, uint32_t);
-extern inline void     draw_get_vector(draw_point_t *, draw_point_t *,
-                           draw_vect_t *);
-extern void            draw_circle_arc(draw_point_t *, int, int, int, int,
-                           uint32_t);
-
-
-
-#endif
diff --git a/tests/sdl-client/tests/fonts.c b/tests/sdl-client/tests/fonts.c
deleted file mode 100644 (file)
index fc6b96f..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-/* $Id: fonts.c,v 1.1 2006/05/03 14:20:47 mmondor Exp $ */
-
-/*
- * Copyright (c) 2004-2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-/* HEADERFILES */
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <SDL.h>
-
-#include <fonts.h>
-#include <screen.h>
-#include <draw.h>
-#include <conf.h>
-
-
-
-/* DEFINITIONS */
-
-#ifdef ANTIALIASING            /* conf,h */
-#define DRAW_SURFACE_COLOR     draw_surface_color_antialias
-#else
-#define DRAW_SURFACE_COLOR     draw_surface_color
-#endif
-
-
-
-/* STATIC FUNCTIONS PROTOTYPES */
-
-inline static void     font_rectangle(font_t *, draw_rect_t *, int);
-
-
-
-/* GLOBALS */
-
-font_t                 *font_small, *font_small_bold,
-                       *font_large, *font_large_bold;
-
-
-
-/* PRIVATE FUNCTIONS */
-
-/*
- * Fills the rectangle coordinates for the specified character of specified
- * font within the font's surface
- */
-inline static void
-font_rectangle(font_t *font, draw_rect_t *rect, int c)
-{
-       assert(font != NULL);
-       assert(rect != NULL);
-
-       /* Make sure that c is within 0-255 */
-       c &= 0xff;
-
-       /* Map c (0-255) to 0-15 x/y coordinates */
-       rect->x = font->x * (c & 0x0f);
-       rect->y = font->y * (c / 16);
-       rect->w = font->x;
-       rect->h = font->y;
-}
-
-
-
-/* PUBLIC FUNCTIONS */
-
-/* Load fonts */
-int
-font_init(void)
-{
-
-       font_small = font_load(
-           "bmp/misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-1.bmp");
-       font_small_bold = font_load(
-           "bmp/misc-fixed-bold-r-normal--13-120-75-75-c-80-iso8859-1.bmp");
-       font_large = font_load(
-         "bmp/misc-fixed-medium-r-normal--15-120-100-100-c-90-iso8859-1.bmp");
-       font_large_bold = font_load(
-           "bmp/misc-fixed-bold-r-normal--15-120-100-100-c-90-iso8859-1.bmp");
-
-       /*
-        * On error, we don't free any successfully loaded fonts, and expect
-        * the application to exit.
-        */
-       if (font_small == NULL || font_small_bold == NULL ||
-           font_large == NULL || font_large_bold == NULL)
-               return -1;
-
-       return 0;
-}
-
-/*
- * Allows to load a 256 characters (16x16 tiled) font map from an image.
- * This image usually is in 1 bit depth, but it internally gets converted to
- * 32-bit depth, and we then create a per-pixel alpha blending enabled surface
- * for it.
- */
-font_t *
-font_load(const char *file)
-{
-       font_t          *font;
-       SDL_Surface     *surface1 = NULL, *surface2 = NULL, *surface3 = NULL;
-       int             ok;
-
-       assert(file != NULL);
-
-       /* Load 1 bit depth bitmap */
-       if ((surface1 = SDL_LoadBMP(file)) == NULL)
-               goto err;
-
-       /*
-        * Convert loaded surface to screen_surface's depth, into new surface.
-        * bits 0 become 0x00000000 and 1 0x00ffffff. Remember that surface2
-        * is the one we'll copy to the final destination one.
-        */
-       if ((surface2 = SDL_ConvertSurface(surface1, screen_surface->format,
-           SDL_SWSURFACE)) == NULL)
-               goto err;
-       SDL_FreeSurface(surface1);
-       surface1 = NULL;
-
-       /*
-        * Create new surface suitable for source alpha blending blitting.
-        * I previously attempted to use the converted surface and create an
-        * alpha blending enabled copy, but this seemed to fail. I thus must
-        * explicitely create a new surface myself (which proved to work in a
-        * test program).
-        */
-       if ((surface1 = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA,
-           surface2->w, surface2->h, 32, 0, 0, 0, 0)) == NULL)
-               goto err;
-
-       /*
-        * Convert newly created surface to support per-pixel alpha blending
-        * with hardware support. Resulting surface3 is the one we'll copy
-        * surface2 to.
-        */
-       (void) SDL_SetAlpha(surface1, SDL_SRCALPHA | SDL_RLEACCEL, 128);
-       if ((surface3 = SDL_DisplayFormatAlpha(surface1)) == NULL)
-               goto err;
-       SDL_FreeSurface(surface1);
-       surface1 = NULL;
-
-       /*
-        * We now have both our 32-bit depth font surface (surface2) and our
-        * destination alpha surface (surface3). Copy surface2 data to
-        * surface3, making sure to set the alpha color to 0x00 for pixels
-        * which originally were 0 bits, that is, now 0x00000000, and to 0xff
-        * for pixels which were 1 bits, now being 0x00ffffff.
-        */
-       ok = -1;
-       if (SDL_LockSurface(surface2) == 0) {
-               if (SDL_LockSurface(surface3) == 0) {
-                       uint32_t        *sptr, *dptr, *dtptr;
-
-                       for (sptr = (uint32_t *)surface2->pixels,
-                           dptr = (uint32_t *)surface3->pixels,
-                           dtptr = &dptr[surface3->w * surface3->h];
-                           dptr < dtptr;
-                           sptr++, dptr++)
-                               *dptr = (*sptr == 0 ? 0x00000000 : 0xffffffff);
-                       ok = 0;
-                       SDL_UnlockSurface(surface3);
-               }
-               SDL_UnlockSurface(surface2);
-       }
-       SDL_FreeSurface(surface2);
-       surface2 = NULL;
-       if (ok == -1)
-               goto err;
-
-       /* Allocate font structure */
-       if ((font = malloc(sizeof(font_t))) == NULL)
-               goto err;
-
-       /* Everything successful, fill font structure and return it. */
-       font->x = surface3->w / 16;
-       font->y = surface3->h / 16;
-       font->surface = surface3;
-
-       return font;
-
-err:
-       if (surface1 != NULL)
-               SDL_FreeSurface(surface1);
-       if (surface2 != NULL)
-               SDL_FreeSurface(surface2);
-       if (surface3 != NULL)
-               SDL_FreeSurface(surface3);
-
-       return NULL;
-}
-
-/* Frees previously loaded font using font_load() */
-void
-font_free(font_t *font)
-{
-
-       assert(font != NULL);
-       assert(font->surface != NULL);
-
-       SDL_FreeSurface(font->surface);
-       free(font);
-}
-
-/*
- * Efficiently draws a character to screen at specified position. The output
- * color however can only be white using this function.
- */
-void
-font_draw_char(font_t *font, draw_point_t *p, int c)
-{
-       SDL_Rect        screen_rect, font_rect;
-       draw_rect_t     r;
-
-       assert(font != NULL);
-       assert(p != NULL);
-
-       screen_rect.x = p->x;
-       screen_rect.y = p->y;
-       font_rectangle(font, &r, c);
-       font_rect = (SDL_Rect){r.x, r.y, r.w, r.h};
-       (void) SDL_BlitSurface(font->surface, &font_rect,
-           screen_surface, &screen_rect);
-}
-
-/*
- * Efficiently draws a character string to screen at specified position.
- * The output color however can only be white using this function.
- */
-void
-font_draw_string(font_t *font, draw_point_t *p, const char *string)
-{
-       register const char     *ptr;
-       SDL_Rect                screen_rect, font_rect;
-       draw_rect_t             r;
-
-       assert(font != NULL);
-       assert(p != NULL);
-       assert(string != NULL);
-
-       screen_rect.x = p->x;
-       screen_rect.y = p->y;
-       for (ptr = string; *ptr != '\0'; ptr++, screen_rect.x += font->x) {
-               font_rectangle(font, &r, *ptr);
-               font_rect = (SDL_Rect){r.x, r.y, r.w, r.h};
-               (void) SDL_BlitSurface(font->surface, &font_rect,
-                   screen_surface, &screen_rect);
-       }
-}
-
-/*
- * Returns the necessary number of horizontal pixels required to blit the
- * specified string.
- */
-int
-font_string_width(font_t *font, const char *string)
-{
-
-       assert(font != NULL);
-       assert(string != NULL);
-
-       return (strlen(string) * font->x);
-}
-
-
-/* The following functions require that the screen surface be locked. */
-
-/*
- * font_draw_char() variant which is a slightly less efficient but allows to
- * blit a character on screen at specified position with specified color.
- * If bg color is 0, font is drawn in overlay mode. Otherwise, it is drawn
- * overstrike with specified color. Note that if calling this function, the
- * screen_surface SDL_Surface should be locked using SDL_LockSurface().
- */
-void
-font_draw_char_color(font_t *font, uint32_t fg, uint32_t bg, draw_point_t *p,
-    int c)
-{
-       draw_rect_t     rect;
-
-       assert(font != NULL);
-       assert(p != NULL);
-
-       font_rectangle(font, &rect, c);
-       DRAW_SURFACE_COLOR(font->surface, &rect, p, fg, bg);
-}
-
-/*
- * font_draw_string() variant which is a little less efficient but allows to
- * blit a character string on screen at specified position with specified
- * color. If bg is 0, string is drawn in overlay mode. Otherwise, it is drawn
- * in overstrike mode with specified background color.
- */
-void
-font_draw_string_color(font_t *font, uint32_t fg, uint32_t bg, draw_point_t *p,
-    const char *string)
-{
-       register const char     *ptr;
-       draw_rect_t             rect;
-
-       assert(font != NULL);
-       assert(p != NULL);
-       assert(string != NULL);
-
-       for (ptr = string; *ptr != '\0'; ptr++, p->x += font->x) {
-               font_rectangle(font, &rect, *ptr);
-               DRAW_SURFACE_COLOR(font->surface, &rect, p, fg, bg);
-       }
-}
diff --git a/tests/sdl-client/tests/fonts.h b/tests/sdl-client/tests/fonts.h
deleted file mode 100644 (file)
index 2edbccd..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* $id$ */
-
-/*
- * Copyright (c) 2004-2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#ifndef FONTS_H
-#define FONTS_H
-
-
-
-#include <SDL.h>
-
-#include <draw.h>
-
-
-
-typedef struct font {
-       int             x, y;
-       SDL_Surface     *surface;
-} font_t;
-
-
-
-extern int             font_init(void);
-extern font_t          *font_load(const char *);
-extern void            font_free(font_t *);
-extern void            font_draw_char(font_t *, draw_point_t *, int);
-extern void            font_draw_string(font_t *, draw_point_t *,
-                           const char *);
-extern int             font_string_width(font_t *, const char *);
-extern void            font_draw_char_color(font_t *, uint32_t, uint32_t,
-                           draw_point_t *, int);
-extern void            font_draw_string_color(font_t *, uint32_t, uint32_t,
-                           draw_point_t *, const char *);
-
-
-extern font_t          *font_small, *font_small_bold,
-                               *font_large, *font_large_bold;
-
-
-
-#endif
diff --git a/tests/sdl-client/tests/msg.c b/tests/sdl-client/tests/msg.c
deleted file mode 100644 (file)
index dc4a14a..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/* $Id: msg.c,v 1.1 2006/04/27 13:26:51 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <SDL.h>
-#include <SDL_thread.h>
-
-#include <thread_msg.h>
-
-
-
-#define        CLIENTS 16
-#define ROUNDS 32
-
-
-
-struct client {
-       SDL_Thread      *thread;
-       int             id;
-};
-
-struct client_msg {
-       thread_msg_t    msg;
-       struct client   *c;
-       int             rounds;
-};
-
-
-
-int            main(int, char **);
-
-static void    done(int);
-static int     thread_client(void *);
-
-
-
-thread_port_t  server_port;
-
-
-
-/* ARGSUSED */
-int
-main(int argc, char **argv)
-{
-       struct client   clients[CLIENTS];
-       int             i;
-       thread_ring_t   server_ring;
-
-       if (SDL_Init(SDL_INIT_EVERYTHING) == -1) {
-               (void) fprintf(stderr, "main() - SDL_Init() - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-
-       /*
-        * We're already the server thread.
-        * Initialize our message port and notification ring.
-        */
-       if (thread_ring_init(&server_ring) == -1) {
-               (void) fprintf(stderr,
-                   "main() - thread_ring_init(server_port) - %s\n",
-                   SDL_GetError());
-               done(EXIT_FAILURE);
-       }
-       if (thread_port_init(&server_port) == -1) {
-               (void) fprintf(stderr,
-                   "main() - thread_port_init(server_port) - %s\n",
-                   SDL_GetError());
-               done(EXIT_FAILURE);
-       }
-       thread_port_set_ring(&server_port, &server_ring);
-
-       /* Launch client threads */
-       for (i = 0; i < CLIENTS; i++) {
-               clients[i].id = i;
-               if ((clients[i].thread = SDL_CreateThread(thread_client,
-                   &clients[i])) == NULL) {
-                       (void) fprintf(stderr,
-                           "main() - SDL_CreateThread(%d) - %s\n",
-                           i, SDL_GetError());
-                       done(EXIT_FAILURE);
-               }
-       }
-
-       /*
-        * Listen for messages from our client threads with a one second
-        * timeout delay and display them.
-        */
-       for (;;) {
-               struct client_msg       *msg;
-
-               while ((msg = (struct client_msg *)thread_msg_get(
-                   &server_port)) != NULL) {
-                       (void) printf("Message from client %d: %d\n",
-                           msg->c->id, msg->rounds);
-                       if (thread_msg_reply(&msg->msg) != 0) {
-                               (void) fprintf(stderr,
-                                   "main() - thread_msg_reply() - %s\n",
-                                   SDL_GetError());
-                               break;
-                       }
-               }
-               (void) printf("Server polling\n");
-               if (thread_ring_wait(&server_ring, 1000) != 0) {
-                       (void) fprintf(stderr,
-                           "main() - thread_ring_wait() - %s\n",
-                           SDL_GetError());
-                       break;
-               }
-       }
-
-       thread_port_set_ring(&server_port, NULL);
-       thread_port_destroy(&server_port);
-       thread_ring_destroy(&server_ring);
-
-       exit(EXIT_SUCCESS);
-}
-
-static void
-done(code)
-{
-
-       SDL_Quit();
-       exit(code);
-}
-
-static int
-thread_client(void *data)
-{
-       struct client           *c = (struct client *)data;
-       struct client_msg       msg, *rmsg;
-       thread_ring_t           client_ring;
-       thread_port_t           client_port;
-       int                     i;
-
-       /* Initialize reply port and ring */
-       if (thread_ring_init(&client_ring) == -1) {
-               (void) fprintf(stderr,
-                   "thread_client(%d) - thread_ring_init(server_port) - %s\n",
-                   c->id, SDL_GetError());
-               done(EXIT_FAILURE);
-       }
-       if (thread_port_init(&client_port) == -1) {
-               (void) fprintf(stderr,
-                   "thread_client(%d) - thread_port_init(server_port) - %s\n",
-                   c->id, SDL_GetError());
-               done(EXIT_FAILURE);
-       }
-       thread_port_set_ring(&client_port, &client_ring);
-
-       /* Initialize message with our reply port */
-       thread_msg_init(&msg.msg, &client_port);
-       msg.c = c;
-
-       for (i = 0; i < ROUNDS; i++) {
-               msg.rounds = i;
-               if (thread_msg_put(&server_port, &msg.msg) == -1) {
-                       (void) fprintf(stderr,
-                           "thread_client(%d) - thread_msg_put(%d) - %s\n",
-                           c->id, i, SDL_GetError());
-                       break;
-               }
-               while ((rmsg = (struct client_msg *)thread_msg_get(
-                   &client_port)) == NULL) {
-                       (void) printf("Client polling\n");
-                       if (thread_ring_wait(&client_ring, 1000) != 0) {
-                               (void) fprintf(stderr,
-                                   "thread_client(%d) - thread_ring_wait(%d)"
-                                   "- %s\n", c->id, i, SDL_GetError());
-                               break;
-                       }
-               }
-               if (rmsg != NULL)
-                       (void) printf("Received reply for %d: %d\n",
-                           rmsg->c->id, rmsg->rounds);
-               else
-                       break;
-       }
-
-       return 0;
-}
diff --git a/tests/sdl-client/tests/netrek-like.c b/tests/sdl-client/tests/netrek-like.c
deleted file mode 100644 (file)
index dbf9e11..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/* $Id: netrek-like.c,v 1.1 2006/05/03 08:58:01 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <SDL.h>
-#include <SDL_rotozoom.h>
-#include <SDL_gfxPrimitives.h>
-
-#include <screen.h>
-#include <fonts.h>
-
-
-
-int                    main(int, char **);
-
-static int             surface_blit_angle(SDL_Surface *, int, int,
-                           double, int);
-static SDL_Surface     *bmp_load_key(const char *);
-
-
-
-/* ARGSUSED */
-int
-main(int argc, char **argv)
-{
-       int             i;
-       SDL_Surface     *rship, *fship;
-
-       screen_init();
-       draw_init();
-       if (font_init() != 0) {
-               (void) fprintf(stderr, "Could not load font bitmaps\n");
-               screen_destroy();
-       }
-
-       rship = bmp_load_key("bmp/RomDD.bmp");
-       fship = bmp_load_key("bmp/FedCA.bmp");
-
-       (void) rectangleRGBA(screen_surface, 0, 0, 750, 750,
-           0xff, 0xff, 0xff, 0xff);
-       (void) rectangleRGBA(screen_surface, 750, 0, 1023, 274,
-           0xff, 0xff, 0xff, 0xff);
-       (void) rectangleRGBA(screen_surface, 750, 274, 1023, 506,
-           0xff, 0xff, 0xff, 0xff);
-       (void) rectangleRGBA(screen_surface, 750, 274, 1023, 767,
-           0xff, 0xff, 0xff, 0xff);
-       (void) rectangleRGBA(screen_surface, 0, 750, 1023, 767,
-           0xff, 0xff, 0xff, 0xff);
-
-       for (i = 0; i < 1440; i += 2) {
-               if (surface_blit_angle(rship, 100, 100, (double)i, 1) == -1 ||
-                   surface_blit_angle(fship, 200, 100, (double)i, 1) == -1)
-                       (void) fprintf(stderr, "surface_blit_angle()\n");
-               SDL_Flip(screen_surface);
-               SDL_Delay(10);
-       }
-
-       SDL_Delay(1000);
-
-       /* Attempt to connect to server */
-
-       screen_destroy();
-       /* NOTREACHED */
-
-       exit(EXIT_SUCCESS);
-}
-
-static SDL_Surface *
-bmp_load_key(const char *file)
-{
-       SDL_Surface     *s;
-       Uint32          c;
-
-       if ((s = SDL_LoadBMP(file)) == NULL)
-               goto err;
-
-       c = SDL_MapRGB(s->format, 0, 0, 0);
-       if (SDL_SetColorKey(s, SDL_SRCCOLORKEY | SDL_RLEACCEL, c) == -1)
-               goto err;
-
-       return s;
-
-err:
-       (void) fprintf(stderr, "bmp_load_key(%s) - %s\n", file, SDL_GetError());
-       screen_destroy();
-       /* NOTREACHED */
-       return NULL;
-}
-
-static int
-surface_blit_angle(SDL_Surface *s, int x, int y, double a, int clean)
-{
-       SDL_Surface     *t;
-       SDL_Rect        d;
-       int             r;
-
-       if (clean) {
-               int     cx, cy, c;
-
-               cx = s->w / 2 + 2;
-               cy = s->h / 2 + 2;
-               c = (cx >= cy ? cx : cy);
-               (void) boxRGBA(screen_surface, x - c, y - c,
-                   x + c, y + c, 0x00, 0x00, 0x00, 0xff);
-       }
-
-       if ((t = rotozoomSurface(s, a, 0.75, 1)) == NULL)
-               return -1;
-
-       d = (SDL_Rect){x - (t->w / 2), y - (t->h / 2), 0, 0};
-       r = SDL_BlitSurface(t, NULL, screen_surface, &d);
-       SDL_FreeSurface(t);
-
-       return r;
-}
diff --git a/tests/sdl-client/tests/rot.c b/tests/sdl-client/tests/rot.c
deleted file mode 100644 (file)
index 18448e8..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/* $Id: rot.c,v 1.3 2006/05/03 08:09:37 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <SDL.h>
-#include <SDL_rotozoom.h>
-#include <SDL_gfxPrimitives.h>
-
-#include <screen.h>
-#include <fonts.h>
-
-
-
-typedef struct angle_cache {
-       SDL_Surface     *source;
-       SDL_Surface     *angles[360];
-} angle_cache_t;
-
-
-
-int                    main(int, char **);
-
-static angle_cache_t   *angle_cache_init(SDL_Surface *);
-static void            angle_cache_destroy(angle_cache_t *);
-static int             surface_blit_angle(struct angle_cache *, int, int,
-                           double, int);
-static SDL_Surface     *bmp_load_key(const char *);
-
-
-
-/* ARGSUSED */
-int
-main(int argc, char **argv)
-{
-       int             i, i2;
-       SDL_Surface     *rship, *fship;
-       angle_cache_t   *rshipc, *fshipc;
-
-       screen_init();
-       draw_init();
-       if (font_init() != 0) {
-               (void) fprintf(stderr, "Could not load font bitmaps\n");
-               screen_destroy();
-       }
-
-       rship = bmp_load_key("bmp/RomDD.bmp");
-       fship = bmp_load_key("bmp/FedCA.bmp");
-       if ((rshipc = angle_cache_init(rship)) == NULL ||
-           (fshipc = angle_cache_init(fship)) == NULL) {
-               (void) fprintf(stderr, "Could not initialize angle caches\n");
-               screen_destroy();
-       }
-
-       for (i2 = 0; i2 < 2; i2++) {
-               for (i = 0; i < 360; i += 5) {
-                       if (surface_blit_angle(rshipc, 100, 100, (double)i, 1)
-                           == -1 || surface_blit_angle(fshipc, 200, 100,
-                           (double)i, 1) == -1)
-                               (void) fprintf(stderr,
-                                   "surface_blit_angle()\n");
-                       SDL_Flip(screen_surface);
-                       SDL_Delay(33);
-               }
-       }
-
-       SDL_Delay(1000);
-
-       /* Attempt to connect to server */
-
-       screen_destroy();
-       /* NOTREACHED */
-
-       exit(EXIT_SUCCESS);
-}
-
-static SDL_Surface *
-bmp_load_key(const char *file)
-{
-       SDL_Surface     *s;
-       Uint32          c;
-
-       if ((s = SDL_LoadBMP(file)) == NULL)
-               goto err;
-
-       c = SDL_MapRGB(s->format, 0, 0, 0);
-       if (SDL_SetColorKey(s, SDL_SRCCOLORKEY | SDL_RLEACCEL, c) == -1)
-               goto err;
-
-       return s;
-
-err:
-       (void) fprintf(stderr, "bmp_load_key(%s) - %s\n", file, SDL_GetError());
-       screen_destroy();
-       /* NOTREACHED */
-       return NULL;
-}
-
-static angle_cache_t *
-angle_cache_init(SDL_Surface *s)
-{
-       angle_cache_t   *ac;
-       int             i;
-
-       assert(s != NULL);
-
-       if ((ac = malloc(sizeof(angle_cache_t))) != NULL) {
-               ac->source = s;
-               for (i = 0; i < 360; i++)
-                       ac->angles[i] = NULL;
-
-               return ac;
-       }
-
-       return NULL;
-}
-
-static void
-angle_cache_destroy(angle_cache_t *ac)
-{
-       int     i;
-
-       assert(ac != NULL);
-
-       for (i = 0; i < 360; i++) {
-               if (ac->angles[i] != NULL)
-                       SDL_FreeSurface(ac->angles[i]);
-       }
-
-       free(ac);
-}
-
-static int
-surface_blit_angle(angle_cache_t *ac, int x, int y, double a, int clean)
-{
-       SDL_Surface     *t, *s = ac->source;
-       SDL_Rect        d;
-       int             r, i;
-
-       assert(a > -1 && a < 360);
-       assert(((int)a) == a);
-
-       if (clean) {
-               int     cx, cy, c;
-
-               cx = s->w / 2 + 2;
-               cy = s->h / 2 + 2;
-               c = (cx >= cy ? cx : cy);
-               (void) boxRGBA(screen_surface, x - c, y - c,
-                   x + c, y + c, 0x00, 0x00, 0x00, 0xff);
-       }
-
-       if ((t = ac->angles[(int)a]) == NULL) {
-               for (r = 0; r < 2; r++) {
-                       if ((t = rotozoomSurface(s, a, 1.0, 1)) != NULL) {
-                               ac->angles[(int)a] = t;
-                               break;
-                       }
-                       /* Free some room and retry */
-                       for (i = 0; i < 360; i++) {
-                               if (ac->angles[i] != NULL) {
-                                       SDL_FreeSurface(ac->angles[i]);
-                                       ac->angles[i] = NULL;
-                               }
-                       }
-               }
-               if (t == NULL)
-                       return -1;
-       }
-
-       d = (SDL_Rect){x - (t->w / 2), y - (t->h / 2), 0, 0};
-       return SDL_BlitSurface(t, NULL, screen_surface, &d);
-}
diff --git a/tests/sdl-client/tests/snd.c b/tests/sdl-client/tests/snd.c
deleted file mode 100644 (file)
index eceaa3c..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/* $Id: snd.c,v 1.1 2006/05/01 03:52:45 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <SDL.h>
-#include <SDL_mixer.h>
-
-
-
-int                    main(int, char **);
-
-static void            done(int);
-static Mix_Chunk       *sample_load(const char *);
-
-
-
-static SDL_Surface     *surface_screen = NULL;
-static Mix_Chunk       *cloak, *uncloak, *shield, *unshield, *torp, *hit,
-                       *explode;
-
-static int             iscloaked, isshielded;
-
-
-
-/* ARGSUSED */
-int
-main(int argc, char **argv)
-{
-       Mix_Music       *mus;
-       SDL_Event       ev;
-
-       if (SDL_Init(SDL_INIT_EVERYTHING) == -1) {
-               (void) fprintf(stderr, "main() - SDL_Init() - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-       if ((surface_screen = SDL_SetVideoMode(640, 480, 32,
-           SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF/* | SDL_FULLSCREEN*/))
-           == NULL) {
-               (void) fprintf(stderr, "main() - SDL_SetVideoMode() - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-
-       if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024) != 0) {
-               (void) fprintf(stderr, "main() - Mix_OpenAudio() - %s\n",
-                   Mix_GetError());
-               done(EXIT_FAILURE);
-       }
-
-       cloak = sample_load("wav/nt_cloaked.wav");
-       uncloak = sample_load("wav/nt_uncloak.wav");
-       shield = sample_load("wav/nt_shield_up.wav");
-       unshield = sample_load("wav/nt_shield_down.wav");
-       torp = sample_load("wav/nt_fire_torp_other.wav");
-       hit = sample_load("wav/nt_plasma_hit.wav");
-       explode = sample_load("wav/nt_explosion_other.wav");
-
-       (void) Mix_AllocateChannels(16);
-       (void) Mix_ReserveChannels(2);
-
-       if ((mus = Mix_LoadMUS("ogg/1.ogg")) == NULL) {
-               (void) fprintf(stderr, "main() - Mix_LoadMUS() - %s\n",
-                   Mix_GetError());
-               done(EXIT_FAILURE);
-       }
-
-       if (Mix_PlayMusic(mus, -1) != 0) {
-               (void) fprintf(stderr, "main() - Mix_PlayMusic() - %s\n",
-                   Mix_GetError());
-               done(EXIT_FAILURE);
-       }
-
-       for (iscloaked = isshielded = 0; SDL_WaitEvent(&ev) != 0; ) {
-               int     ch;
-
-               if (ev.type == SDL_KEYUP && ev.key.keysym.sym == SDLK_ESCAPE)
-                       break;
-               if (ev.type == SDL_KEYDOWN) {
-                       switch (ev.key.keysym.sym) {
-                       case SDLK_SPACE:
-                               /* Torp */
-                               if ((ch = Mix_PlayChannel(-1, torp, 0)) == -1)
-                                       (void) fprintf(stderr, "main() - "
-                                           "Mix_PlayChannel(torp) - %s\n",
-                                           SDL_GetError());
-                               else
-                                       Mix_SetPosition(ch, rand() % 359,
-                                           255 - (200 + (rand() % 54)));
-                               break;
-                       case SDLK_w:
-                               /* Cloak toggle */
-                               iscloaked = (iscloaked == 0 ? 1 : 0);
-                               if (Mix_PlayChannel(0,
-                                   (iscloaked == 1 ? cloak : uncloak), 0)
-                                   == -1)
-                                       (void) fprintf(stderr, "main() - "
-                                           "Mix_PlayChannel(cloack) - %s\n",
-                                           SDL_GetError());
-                               break;
-                       case SDLK_s:
-                               /* Shield toggle */
-                               isshielded = (isshielded == 0 ? 1 : 0);
-                               if (Mix_PlayChannel(1,
-                                   (isshielded == 1 ? shield : unshield), 0)
-                                   == -1)
-                                       (void) fprintf(stderr, "main() - "
-                                           "Mix_PlayChannel(shield) - %s\n",
-                                           SDL_GetError());
-                               break;
-                       default:
-                               break;
-                       }
-               }
-       }
-
-       if (Mix_FadeOutMusic(2000))
-               SDL_Delay(2000);
-
-       Mix_HaltMusic();
-       Mix_CloseAudio();
-
-       done(EXIT_SUCCESS);
-       /* NOTREACHED */
-       exit(EXIT_SUCCESS);
-}
-
-static void
-done(code)
-{
-
-       SDL_Quit();
-       exit(code);
-}
-
-static Mix_Chunk *
-sample_load(const char *file)
-{
-       Mix_Chunk       *c;
-
-       if ((c = Mix_LoadWAV(file)) == NULL) {
-               (void) fprintf(stderr,
-                   "sample_load() - Mix_LoadWAV(%s) - %s\n",
-                   file, SDL_GetError());
-               done(EXIT_FAILURE);
-       }
-
-       return c;
-}
diff --git a/tests/sdl-client/thread_msg.c b/tests/sdl-client/thread_msg.c
deleted file mode 100644 (file)
index 3652617..0000000
+++ /dev/null
@@ -1,432 +0,0 @@
-/* $Id: thread_msg.c,v 1.12 2006/05/19 10:14:35 mmondor Exp $ */
-
-/*
- * Copyright (C) 2006, Matthew Mondor
- * All rights reserved.
- *
- * Adapted from older code intended for use with POSIX threads,
- * for use within SDL.
- */
-
-
-
-#include <stdlib.h>
-
-#include <debug.h>
-#include <thread_msg.h>
-#include <pool.h>
-
-
-
-static int             amsg_create(pnode_t *);
-static void            amsg_destroy(pnode_t *);
-
-
-
-static pool_t          amsg_pool;
-static SDL_mutex       *amsg_mutex;
-static int             amsg_initialized = 0;
-
-
-
-/*
- * Allows to initialize a polling notification handle.  When attached to a
- * port, a message arriving on an empty port causes the associated ring to
- * wake the thread from thread_ring_wait().
- */
-int
-thread_ring_init(thread_ring_t *ring)
-{
-
-       ASSERT(ring != NULL && ring->magic != PRING_MAGIC);
-
-       if ((ring->cond = SDL_CreateCond()) != NULL) {
-               if ((ring->mutex = SDL_CreateMutex()) != NULL) {
-                       ring->event = 0;
-                       ring->magic = PRING_MAGIC;
-
-                       return 0;
-               }
-               SDL_DestroyCond(ring->cond);
-       }
-
-       return -1;
-}
-
-/*
- * Returns TRUE if the supplied ring is a valid/usable one, or FALSE
- * otherwise.  Useful to conditionally destroy it.
- */
-int
-thread_ring_valid(thread_ring_t *ring)
-{
-
-       ASSERT(ring != NULL);
-
-       return (ring != NULL && ring->magic == PRING_MAGIC);
-}
-
-/*
- * Destroys a ring.  Note that all message ports attached to this ring should
- * first be detached or destroyed.
- */
-void
-thread_ring_destroy(thread_ring_t *ring)
-{
-
-       ASSERT(ring != NULL && ring->magic == PRING_MAGIC);
-
-       SDL_DestroyMutex(ring->mutex);
-       SDL_DestroyCond(ring->cond);
-       ring->magic = 0;
-}
-
-/*
- * Causes the current thread to sleep until a message arrives on an empty port
- * associated with this ring.  In normal operation, a thread only goes in wait
- * mode after it processed all queued messages on all interesting ports.
- * The ring is only notified when the port is empty and that a message is
- * queued into it.
- */
-int
-thread_ring_wait(thread_ring_t *ring, Uint32 ms)
-{
-       int     error = 0;
-
-       ASSERT(ring != NULL && ring->magic == PRING_MAGIC);
-
-       /* We must hold the condition variable's mutex */
-       if (SDL_LockMutex(ring->mutex) != 0) {
-               error = -1;
-               goto err;
-       }
-
-       /* As long as we don't have confirmation that we must stop waiting */
-       for (ring->event = 0; !ring->event && error == 0; ) {
-               /*
-                * Wait on conditional variable, which will automatically
-                * and atomically release the mutex and return with the mutex
-                * locked again, as soon as the conditional variable gets
-                * signaled.
-                */
-               if (ms != 0)
-                       error = SDL_CondWaitTimeout(ring->cond, ring->mutex,
-                           ms);
-               else
-                       error = SDL_CondWait(ring->cond, ring->mutex);
-       }
-
-       /*
-        * And we know that conditional waiting functions returned with mutex
-        * locked, so now release it back.
-        */
-       (void) SDL_UnlockMutex(ring->mutex);
-
-err:
-       return error;
-}
-
-/*
- * Allows to wake up waiter(s) on the specified ring, which are sleeping
- * threads within thread_ring_wait().  This can be used to simulate the
- * arrival of a message on an empty port.  Also useful to use rings as a
- * notification system only when no message passing is needed.
- */
-int
-thread_ring_notify(thread_ring_t *ring)
-{
-
-       ASSERT(ring != NULL && ring->magic == PRING_MAGIC);
-
-       if (SDL_LockMutex(ring->mutex) != 0)
-               return -1;
-
-       ring->event = 1;
-       (void) SDL_CondSignal(ring->cond);
-
-       (void) SDL_UnlockMutex(ring->mutex);
-
-       return 0; 
-}
-
-/*
- * Allows to initialize/create a message port.
- */
-int
-thread_port_init(thread_port_t *port)
-{
-
-       ASSERT(port != NULL && port->magic != PPORT_MAGIC);
-
-       if ((port->lock = SDL_CreateMutex()) == NULL)
-               return -1;
-
-       port->magic = PPORT_MAGIC;
-       port->ring = NULL;
-       DLIST_INIT(&port->messages);
-
-       return 0;
-}
-
-/*
- * Returns TRUE if the supplied port is valid/usable, or FALSE otherwise.
- * Useful to conditionally destroy a port, for instance.
- */
-int
-thread_port_valid(thread_port_t *port)
-{
-
-       return (port != NULL && port->magic == PPORT_MAGIC);
-}
-
-/*
- * Destroys the specified port, previously created using thread_port_init().
- */
-void
-thread_port_destroy(thread_port_t *port)
-{
-
-       ASSERT(port != NULL && port->magic == PPORT_MAGIC);
-
-       port->magic = 0;
-       SDL_DestroyMutex(port->lock);
-}
-
-/*
- * Attaches a port to a ring.  Multiple ports may be attached to a ring.  A
- * message arriving on an empty port will cause the attached ring to be
- * notified, if any, and as such to cause a thread waiting on the ring to
- * be awakened.
- */
-void
-thread_port_set_ring(thread_port_t *port, thread_ring_t *ring)
-{
-
-       ASSERT(port != NULL && port->magic == PPORT_MAGIC &&
-           (ring == NULL || ring->magic == PRING_MAGIC));
-
-       port->ring = ring;
-}
-
-/*
- * Allows to initialize a message before it can be sent over a port.  The
- * message only needs to be initialized once in general, even if it will be
- * used for bidirectional transmission for synchronous operation.  If the
- * reply port needs to be changed, however, this function should be used again
- * to set the new reply port.
- */
-void
-thread_msg_init(thread_msg_t *msg, thread_port_t *rport)
-{
-
-       ASSERT(msg != NULL && msg->magic != PMESG_MAGIC &&
-           (rport == NULL || rport->magic == PPORT_MAGIC));
-
-       msg->magic = PMESG_MAGIC;
-       msg->reply = rport;
-}
-
-/*
- * Returns TRUE if supplied message is valid/usable or FALSE otherwise.
- */
-int
-thread_msg_valid(thread_msg_t *msg)
-{
-
-       return (msg != NULL && msg->magic == PMESG_MAGIC);
-}
-
-/*
- * Invalidates a message, so that it can no longer be sent over ports.
- */
-void
-thread_msg_destroy(thread_msg_t *msg)
-{
-
-       ASSERT(msg != NULL && msg->magic == PMESG_MAGIC);
-
-       msg->magic = 0;
-}
-
-/*
- * If any message exists in the queue of the specified port, unqueues it and
- * returns it.  Otherwise, NULL is returned.  In normal operation, all messages
- * queued to a port are processed before putting the thread back into sleep,
- * mainly for efficiency, but also because it eases synchronization.
- */
-thread_msg_t *
-thread_msg_get(thread_port_t *port)
-{
-       thread_msg_t    *msg = NULL;
-
-       ASSERT(port != NULL && port->magic == PPORT_MAGIC);
-
-       if (SDL_LockMutex(port->lock) != 0)
-               goto err;
-
-       if ((msg = DLIST_TOP(&port->messages)) != NULL) {
-               ASSERT(msg->magic == PMESG_MAGIC);
-               DLIST_UNLINK(&port->messages, (node_t *)msg);
-       }
-
-       (void) SDL_UnlockMutex(port->lock);
-
-err:
-       return (thread_msg_t *)msg;
-}
-
-/*
- * Queues the specified message to the specified port, returning 0 on success.
- * Note that the message data is not copied or moved, but that a pointer
- * system is used to queue the message.  Thus, the message's shared memory
- * region is leased temporarily to the other end.  One has to be careful to
- * not allocate this message space on the stack when asynchroneous operation
- * is needed.  In synchroneous operation mode, it is not a problem, since the
- * sender does not have to modify the data until the other end replies back
- * with the same message after modifying the message if necessary.  In
- * synchroneous mode, we simply delegate that message memory region to the
- * other end until it notifies us with a reply that it is done working with
- * it.  Returns 0 on success, or -1 on error.
- */
-int
-thread_msg_put(thread_port_t *port, thread_msg_t *msg)
-{
-
-       ASSERT(port != NULL && port->magic == PPORT_MAGIC &&
-           msg != NULL && msg->magic == PMESG_MAGIC);
-
-       if (SDL_LockMutex(port->lock) != 0)
-               return -1;
-
-       DLIST_APPEND(&port->messages, (node_t *)msg);
-       if (port->ring != NULL) {
-               if (DLIST_NODES(&port->messages) == 1) {
-                       /*
-                        * We know that there previously were no messages,
-                        * and that the reading thread then waits for any
-                        * message to be available.  Signal it that there at
-                        * least is one message ready.  The other end should
-                        * normally process all available messages before
-                        * going back into waiting.
-                        */
-                       if (SDL_LockMutex(port->ring->mutex) == 0) {
-                               port->ring->event = 1;
-                               (void) SDL_CondSignal(port->ring->cond);
-                               (void) SDL_UnlockMutex(port->ring->mutex);
-                       }
-               }
-       }
-
-       (void) SDL_UnlockMutex(port->lock);
-
-       return 0;
-}
-
-/*
- * Meant to be used in synchroneous message transfer mode.  The initial sender
- * sends a message to the other end, which then uses this function to notify
- * back the initial sender that it is done, often with a success/failure
- * result as part of the message.  Returns 0 on success, or -1 on error.
- */
-int
-thread_msg_reply(thread_msg_t *msg)
-{
-
-       ASSERT(msg != NULL && msg->magic == PMESG_MAGIC && msg->reply != NULL);
-
-       return thread_msg_put(msg->reply, msg);
-}
-
-/*
- * Returns the number of pending messages tied to the port, if any, or -1
- * on error.
- */
-int
-thread_port_pending(thread_port_t *port)
-{
-       int     pending = -1;
-
-       ASSERT(port != NULL && port->magic == PPORT_MAGIC);
-
-       if (SDL_LockMutex(port->lock) == 0) {
-               pending = (int)DLIST_NODES(&port->messages);
-               (void) SDL_UnlockMutex(port->lock);
-       }
-
-       return pending;
-}
-
-/*
- * Initializes the asynchroneous messages pool and mutex.  Must be called
- * before thread_amsg_create() and thread_amsg_destroy() can be used.
- * Returns 0 on success or -1 on error.
- */
-int
-thread_amsg_pool_init(void)
-{
-
-       if (pool_init(&amsg_pool, "amsg_pool", malloc, free, amsg_create,
-           amsg_destroy, sizeof(thread_amsg_t), 64, 1, 0) == -1)
-               return -1;
-
-       if ((amsg_mutex = SDL_CreateMutex()) == NULL) {
-               pool_destroy(&amsg_pool);
-               return -1;
-       }
-
-       amsg_initialized = 1;
-
-       return 0;
-}
-
-static int
-amsg_create(pnode_t *p)
-{
-
-       thread_msg_init((thread_msg_t *)p, NULL);
-
-       return 0;
-}
-
-static void
-amsg_destroy(pnode_t *p)
-{
-
-       thread_msg_destroy((thread_msg_t *)p);
-}
-
-/*
- * Creates an amsg and returns a pointer to it, or NULL on failure.
- * This is useful to efficiently create/send asynchroneous messages to
- * another thread which is expected to receive/destroy it asynchroneously
- * without replying, in which case a pool of distinct messages must be used.
- */
-thread_amsg_t *
-thread_amsg_create(void)
-{
-       thread_amsg_t   *amsg = NULL;
-
-       ASSERT(amsg_initialized);
-
-       if (SDL_LockMutex(amsg_mutex) == 0) {
-               amsg = (thread_amsg_t *)pool_alloc(&amsg_pool, 0);
-               SDL_UnlockMutex(amsg_mutex);
-       }
-
-       return amsg;
-}
-
-/*
- * Destroys an amsg previously created with thread_amsg_create().
- */
-void
-thread_amsg_destroy(thread_amsg_t *amsg)
-{
-
-       ASSERT(amsg_initialized && amsg != NULL);
-
-       if (SDL_LockMutex(amsg_mutex) == 0) {
-               (void) pool_free((pnode_t *)amsg);
-               SDL_UnlockMutex(amsg_mutex);
-       }
-}
diff --git a/tests/sdl-client/thread_msg.h b/tests/sdl-client/thread_msg.h
deleted file mode 100644 (file)
index 157cad8..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/* $Id: thread_msg.h,v 1.9 2006/05/19 10:14:35 mmondor Exp $ */
-
-/*
- * Copyright (C) 2006, Matthew Mondor
- * All rights reserved.
- *
- * Adapted from older code intended for use with POSIX threads,
- * for use within SDL.
- */
-
-
-
-#ifndef THREAD_MSG_H
-#define THREAD_MSG_H
-
-
-
-#include <stdint.h>
-
-#include <SDL.h>
-#include <SDL_thread.h>
-
-#include <dlist.h>
-#include <pool.h>
-
-
-
-#define PRING_MAGIC    0x50524e47
-#define        PPORT_MAGIC     0x50505254
-#define PMESG_MAGIC    0x504d5347
-
-#define AMSG_MAXSIZE   256
-
-typedef struct {
-       uint32_t        magic;
-       SDL_cond        *cond;
-       SDL_mutex       *mutex;
-       int             event;
-} thread_ring_t;
-
-typedef struct {
-       uint32_t        magic;
-       thread_ring_t   *ring;
-       SDL_mutex       *lock;
-       list_t          messages;
-} thread_port_t;
-
-typedef struct {
-       pnode_t         node;
-       uint32_t        magic;
-       thread_port_t   *reply;
-} thread_msg_t;
-
-typedef struct {
-       thread_msg_t    msg;
-       size_t          size;
-       uint32_t        data[AMSG_MAXSIZE / 4];
-} thread_amsg_t;
-
-
-
-extern int             thread_ring_init(thread_ring_t *);
-extern int             thread_ring_valid(thread_ring_t *);
-extern void            thread_ring_destroy(thread_ring_t *);
-extern int             thread_ring_wait(thread_ring_t *, Uint32);
-extern int             thread_ring_notify(thread_ring_t *);
-
-extern int             thread_port_init(thread_port_t *);
-extern int             thread_port_valid(thread_port_t *);
-extern void            thread_port_destroy(thread_port_t *);
-extern void            thread_port_set_ring(thread_port_t *, thread_ring_t *);
-extern void            thread_msg_init(thread_msg_t *, thread_port_t *);
-extern int             thread_msg_valid(thread_msg_t *);
-extern void            thread_msg_destroy(thread_msg_t *);
-extern thread_msg_t    *thread_msg_get(thread_port_t *);
-extern int             thread_msg_put(thread_port_t *, thread_msg_t *);
-extern int             thread_msg_reply(thread_msg_t *);
-extern int             thread_port_pending(thread_port_t *);
-
-extern int             thread_amsg_pool_init(void);
-extern thread_amsg_t   *thread_amsg_create(void);
-extern void            thread_amsg_destroy(thread_amsg_t *);
-
-
-
-#endif
diff --git a/tests/sdl-client/thread_net_recv.c b/tests/sdl-client/thread_net_recv.c
deleted file mode 100644 (file)
index efa0da0..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/* $Id: thread_net_recv.c,v 1.4 2006/05/19 14:54:38 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * User events polling thread.  Reports all events to the master thread
- * via efficient inter-thread messages.
- */
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <main.h>
-#include <thread_net_recv.h>
-#include <conf.h>
-
-
-
-static void            ssend(thread_msg_t *);
-static int             state_connect(void);
-static void            state_recv(void);
-static ssize_t         server_recv(void *, size_t);
-
-
-
-static thread_ring_t   recv_ring;
-static thread_port_t   recv_port;
-
-
-
-TCPsocket              server_socket = NULL;
-
-
-
-int
-thread_net_recv(void *data)
-{
-
-       /* Initialize reply port and ring */
-       if (thread_ring_init(&recv_ring) == -1) {
-               (void) fprintf(stderr,
-                   "thread_net_recv() - thread_ring_init(recv_port) - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-       if (thread_port_init(&recv_port) == -1) {
-               (void) fprintf(stderr,
-                   "thread_net_recv() - thread_port_init(recv_port) - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-       thread_port_set_ring(&recv_port, &recv_ring);
-
-       if (state_connect() == 0)
-               state_recv();
-
-       /* Wait peacefully until our process exits */
-       for (;;)
-               (void) thread_ring_wait(&recv_ring, -1);
-
-       /* NOTREACHED */
-
-       return 0;
-}
-
-/*
- * Sends a message synchroneously, that is, sends and waits for a reply.
- */
-static void
-ssend(thread_msg_t *msg)
-{
-       thread_msg_t    *rmsg;
-
-       if (thread_msg_put(&main_port, msg) == -1)
-               (void) fprintf(stderr,
-                   "ssend() - thread_msg_put()\n");
-       while ((rmsg = thread_msg_get(&recv_port)) == NULL) {
-               if (thread_ring_wait(&recv_ring, -1) != 0)
-                       (void) fprintf(stderr,
-                           "ssend() - thread_ring_wait()\n");
-       }
-}
-
-/*
- * Attempts to connect to server.  On success, 0 is returned and a success
- * reply packet is sent synchroneously to the main thread.  On error, a
- * failure packet is sent instead and we return -1.
- */
-static int
-state_connect(void)
-{
-       struct msg_connect      msg;
-       IPaddress               addr;
-
-       thread_msg_init(&msg.msg, &recv_port);
-       msg.status = 0;
-       msg.error = NULL;
-
-       if (SDLNet_ResolveHost(&addr, SERVER_HOST, SERVER_PORT) != 0) {
-               msg.status = -1;
-               msg.error = "Could not resolve server hostname";
-               goto end;
-       }
-
-       if ((server_socket = SDLNet_TCP_Open(&addr)) == NULL) {
-               msg.status = -1;
-               msg.error = "Could not connect to server";
-       }
-
-end:
-       ssend(&msg.msg);
-
-       return 0;
-}
-
-/*
- * We endlessly read packets from the server and queue them asynchroneously to
- * the main thread's port, unless a read error occurs, in which case we queue
- * an empty/error special packet and return.
- */
-static void
-state_recv(void)
-{
-       thread_amsg_t   *amsg = NULL;
-
-       for (;;) {
-               uint8_t type, length;
-
-               /*
-                * We must already have an allocated message since we'll read
-                * data directly into its buffer.  If this operation fails,
-                * it's fatal since the receiving main thread will never be
-                * notified.
-                */
-               if ((amsg = thread_amsg_create()) == NULL) {
-                       (void) fprintf(stderr,
-                           "state_recv() - thread_amsg_create()\n");
-                       exit(EXIT_FAILURE);
-               }
-
-               /*
-                * Start reading a single byte, the message type, and evaluate
-                * the message size.  For variable packets, we also must read
-                * another byte for the legth.  Then read the remaining of the
-                * message.  On any invalid message, we error and stop as if
-                * the connection had problems, but we log it.  Upon
-                * successful reception of a complete message, directly
-                * transmit it to the main thread asynchroneously and
-                * continue for another packet.  These read operations are
-                * blocking automatically when no data is available to read.
-                */
-               if (server_recv(amsg->data, 16) == -1)
-                       break;
-               type = *(amsg->data);
-
-               /* XXX */
-               amsg->size = 16;
-
-               /* Valid fixed length packet type?  If so, set length */
-               /* Valid variable length packet type?  Obtain length */
-
-               /* Read remaining of packet */
-
-               /* Asynchroneously send packet to the main thread */
-               (void) thread_msg_put(&main_port, &amsg->msg);
-       }
-
-       /* Send the end of stream message to the main thread */
-       amsg->size = -1;
-       (void) thread_msg_put(&main_port, &amsg->msg);
-}
-
-static ssize_t
-server_recv(void *data, size_t size)
-{
-       size_t  len;
-       int     res;
-
-       for (len = 0; len < size; len += res) {
-               if ((res = SDLNet_TCP_Recv(server_socket, data + len,
-                   size - len)) < 1)
-                       return -1;
-       }
-
-       return len;
-}
diff --git a/tests/sdl-client/thread_net_recv.h b/tests/sdl-client/thread_net_recv.h
deleted file mode 100644 (file)
index 7a977e2..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* $Id: thread_net_recv.h,v 1.1 2006/05/19 09:13:42 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * User events polling thread.  Reports all events to the master thread
- * via efficient inter-thread messages.
- */
-
-
-
-#ifndef THREAD_NET_RECV_H
-#define THREAD_NET_RECV_H
-
-
-
-#include <SDL.h>
-#include <SDL_net.h>
-
-#include <thread_msg.h>
-
-
-
-/*
- * The initial message we're waiting for from the read thread.  The read
- * thread will attempt to connect to the server, initiate authentication and
- * then reply using this message with the connection status.  Afterwards, we
- * only expect msg_read packets from that thread.
- * <status> will be 0 on success or -1 on failure, in which case the error
- * message string will be found into <error>.
- */
-struct msg_connect {
-       thread_msg_t    msg;
-       int             status;
-       const char      *error;
-};
-
-/*
- * We receive such a message when a packet was successfully read from the
- * server.  We reply in a synchroneous manner, however the reply delay should
- * be very short compared to the possible delay of the read thread during a
- * blocking read (SDL_net does not support non-blocking I/O operations).
- * If -1 is received for the <data> size, with a NULL <data> pointer, it means
- * that the connection status was lost or that a timeout occurred.
- */
-struct msg_recv {
-       thread_msg_t    msg;
-       void            *data;
-       size_t          size;
-};
-
-
-
-int                    thread_net_recv(void *);
-
-
-
-extern TCPsocket       server_socket;
-
-
-
-#endif
diff --git a/tests/sdl-client/thread_net_send.c b/tests/sdl-client/thread_net_send.c
deleted file mode 100644 (file)
index 4fe7e21..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/* $Id: thread_net_send.c,v 1.1 2006/05/19 09:13:42 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Server socket writing thread.  We post all asynchroneous messages
- * (thread_amsg_t) we receive from the main thread to the server socket.
- */
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <thread_net_send.h>
-#include <thread_net_recv.h>
-
-
-
-static thread_ring_t   send_ring;
-
-
-
-thread_port_t          send_port;
-
-
-
-int
-thread_net_send(void *data)
-{
-       thread_amsg_t   *amsg;
-
-       /* Initialize reply port and ring */
-       if (thread_ring_init(&send_ring) == -1) {
-               (void) fprintf(stderr,
-                   "thread_net_recv() - thread_ring_init(send_port) - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-       if (thread_port_init(&send_port) == -1) {
-               (void) fprintf(stderr,
-                   "thread_net_send() - thread_port_init(send_port) - %s\n",
-                   SDL_GetError());
-               exit(EXIT_FAILURE);
-       }
-       thread_port_set_ring(&send_port, &send_ring);
-
-       /*
-        * Simply process all incomming messages, sending their data to
-        * the server port, and discarding the messages.  When the port is
-        * empty, wait polling until messages become available.
-        */
-       for (;;) {
-               while ((amsg = (thread_amsg_t *)thread_msg_get(&send_port))
-                      != NULL) {
-                       if (SDLNet_TCP_Send(server_socket,
-                           amsg->data, amsg->size) != amsg->size)
-                               (void) fprintf(stderr,
-                                   "Error writing to server socket\n");
-                       thread_amsg_destroy(amsg);
-               }
-               (void) thread_ring_wait(&send_ring, -1);
-       }
-
-       /* NOTREACHED */
-
-       return 0;
-}
diff --git a/tests/sdl-client/thread_net_send.h b/tests/sdl-client/thread_net_send.h
deleted file mode 100644 (file)
index f1ae02f..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* $Id: thread_net_send.h,v 1.1 2006/05/19 09:13:42 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-/*
- * Server socket writing thread.  We post all asynchroneous messages
- * (thread_amsg_t) we receive from the main thread to the server socket.
- */
-
-
-
-#ifndef THREAD_NET_SEND_H
-#define THREAD_NET_SEND_H
-
-
-
-#include <SDL.h>
-#include <SDL_net.h>
-
-#include <thread_msg.h>
-
-
-
-int                    thread_net_send(void *);
-
-
-
-extern thread_port_t   send_port;
-
-
-
-#endif
diff --git a/tests/sdl-client/wav/README b/tests/sdl-client/wav/README
deleted file mode 100644 (file)
index 8c7a92a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-For now these have been borrowed from the netrekxp client.
diff --git a/tests/sdl-client/wav/nt_cloaked.wav b/tests/sdl-client/wav/nt_cloaked.wav
deleted file mode 100755 (executable)
index 3e010dd..0000000
Binary files a/tests/sdl-client/wav/nt_cloaked.wav and /dev/null differ
diff --git a/tests/sdl-client/wav/nt_explosion_other.wav b/tests/sdl-client/wav/nt_explosion_other.wav
deleted file mode 100755 (executable)
index b7ba8cb..0000000
Binary files a/tests/sdl-client/wav/nt_explosion_other.wav and /dev/null differ
diff --git a/tests/sdl-client/wav/nt_fire_torp_other.wav b/tests/sdl-client/wav/nt_fire_torp_other.wav
deleted file mode 100755 (executable)
index dddf2c6..0000000
Binary files a/tests/sdl-client/wav/nt_fire_torp_other.wav and /dev/null differ
diff --git a/tests/sdl-client/wav/nt_plasma_hit.wav b/tests/sdl-client/wav/nt_plasma_hit.wav
deleted file mode 100755 (executable)
index 73ecd7c..0000000
Binary files a/tests/sdl-client/wav/nt_plasma_hit.wav and /dev/null differ
diff --git a/tests/sdl-client/wav/nt_shield_down.wav b/tests/sdl-client/wav/nt_shield_down.wav
deleted file mode 100755 (executable)
index 0888f08..0000000
Binary files a/tests/sdl-client/wav/nt_shield_down.wav and /dev/null differ
diff --git a/tests/sdl-client/wav/nt_shield_up.wav b/tests/sdl-client/wav/nt_shield_up.wav
deleted file mode 100755 (executable)
index 909f72c..0000000
Binary files a/tests/sdl-client/wav/nt_shield_up.wav and /dev/null differ
diff --git a/tests/sdl-client/wav/nt_uncloak.wav b/tests/sdl-client/wav/nt_uncloak.wav
deleted file mode 100755 (executable)
index e4df979..0000000
Binary files a/tests/sdl-client/wav/nt_uncloak.wav and /dev/null differ
diff --git a/tests/zlib/README b/tests/zlib/README
deleted file mode 100644 (file)
index aa38152..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-$Id: README,v 1.1 2006/06/15 14:23:24 mmondor Exp $
-
-Simple zlib compression/decompression tests.
diff --git a/tests/zlib/deflate.c b/tests/zlib/deflate.c
deleted file mode 100644 (file)
index 7eff3e4..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* $Id: deflate.c,v 1.1 2006/06/15 14:23:24 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <zlib.h>
-
-
-
-#define RBUF_SIZE      4096
-#define DBUF_SIZE      (RBUF_SIZE * 2)
-
-
-
-int    main(void);
-
-
-
-int
-main(void)
-{
-       z_stream        s;
-       char            rbuf[RBUF_SIZE], dbuf[DBUF_SIZE];
-       size_t          size;
-
-       if (setvbuf(stdin, NULL, _IONBF, 0) == EOF)
-               perror("setvbuf(stdin)");
-       if (setvbuf(stdout, NULL, _IONBF, 0) == EOF)
-               perror("setvbuf(stdout)");
-
-       s.next_in = s.next_out = NULL;
-       s.avail_in = s.avail_out = 0;
-       s.zalloc = NULL;
-       s.zfree = NULL;
-       s.opaque = NULL;
-
-       if (deflateInit(&s, Z_DEFAULT_COMPRESSION) != Z_OK) {
-               perror("deflateInit()");
-               exit(EXIT_FAILURE);
-       }
-
-       while (!feof(stdin) && !ferror(stdin)) {
-               if ((size = fread(rbuf, 1, RBUF_SIZE, stdin)) < 1)
-                       continue;
-               s.next_in = rbuf;
-               s.avail_in = size;
-               s.next_out = dbuf;
-               s.avail_out = DBUF_SIZE;
-               if (deflate(&s, Z_NO_FLUSH/*Z_SYNC_FLUSH*/) != Z_OK) {
-                       perror("deflate()");
-                       exit(EXIT_FAILURE);
-               }
-               if (fwrite(dbuf, 1, DBUF_SIZE - s.avail_out, stdout)
-                   != DBUF_SIZE - s.avail_out) {
-                       perror("fwrite()");
-                       exit(EXIT_FAILURE);
-               }
-       }
-
-       s.next_in = rbuf;
-       s.avail_in = 0;
-       s.next_out = dbuf;
-       s.avail_out = DBUF_SIZE;
-       if (deflate(&s, Z_FINISH) != Z_STREAM_END) {
-               perror("deflate()");
-               exit(EXIT_FAILURE);
-       }
-       if (fwrite(dbuf, 1, DBUF_SIZE - s.avail_out, stdout)
-           != DBUF_SIZE - s.avail_out) {
-               perror("fwrite()");
-               exit(EXIT_FAILURE);
-       }
-
-       if (deflateEnd(&s) != Z_OK) {
-               perror("deflateEnd()");
-               exit(EXIT_FAILURE);
-       }
-
-       exit(feof(stdin) ? EXIT_SUCCESS : EXIT_FAILURE);
-}
diff --git a/tests/zlib/inflate.c b/tests/zlib/inflate.c
deleted file mode 100644 (file)
index 59b807b..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/* $Id: inflate.c,v 1.1 2006/06/15 14:23:24 mmondor Exp $ */
-
-/*
- * Copyright (c) 2006, Matthew Mondor
- * ALL RIGHTS RESERVED.
- */
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <zlib.h>
-
-
-
-#define RBUF_SIZE      4096
-#define IBUF_SIZE      (RBUF_SIZE * 64)
-
-
-
-int    main(void);
-
-
-
-int
-main(void)
-{
-       z_stream        s;
-       char            rbuf[RBUF_SIZE], ibuf[IBUF_SIZE];
-       size_t          size;
-       int             ret;
-
-       if (setvbuf(stdin, NULL, _IONBF, 0) == EOF)
-               perror("setvbuf(stdin)");
-       if (setvbuf(stdout, NULL, _IONBF, 0) == EOF)
-               perror("setvbuf(stdout)");
-
-       s.next_in = s.next_out = NULL;
-       s.avail_in = s.avail_out = 0;
-       s.zalloc = NULL;
-       s.zfree = NULL;
-       s.opaque = NULL;
-
-       if (inflateInit(&s) != Z_OK) {
-               perror("inflateInit()");
-               exit(EXIT_FAILURE);
-       }
-
-       while (!feof(stdin) && !ferror(stdin)) {
-               if ((size = fread(rbuf, 1, RBUF_SIZE, stdin)) < 1)
-                       continue;
-               s.next_in = rbuf;
-               s.avail_in = size;
-               s.next_out = ibuf;
-               s.avail_out = IBUF_SIZE;
-               if ((ret = inflate(&s, Z_SYNC_FLUSH)) != Z_OK &&
-                   ret != Z_STREAM_END) {
-                       perror("inflate()");
-                       exit(EXIT_FAILURE);
-               }
-               if (fwrite(ibuf, 1, IBUF_SIZE - s.avail_out, stdout)
-                   != IBUF_SIZE - s.avail_out) {
-                       perror("fwrite()");
-                       exit(EXIT_FAILURE);
-               }
-               if (ret == Z_STREAM_END)
-                       break;
-       }
-
-       s.next_in = rbuf;
-       s.avail_in = 0;
-       s.next_out = ibuf;
-       s.avail_out = IBUF_SIZE;
-       if (inflate(&s, Z_FINISH) != Z_STREAM_END) {
-               perror("inflate()");
-               exit(EXIT_FAILURE);
-       }
-       if (fwrite(ibuf, 1, IBUF_SIZE - s.avail_out, stdout)
-           != IBUF_SIZE - s.avail_out) {
-               perror("fwrite()");
-               exit(EXIT_FAILURE);
-       }
-
-       if (inflateEnd(&s) != Z_OK) {
-               perror("inflateEnd()");
-               exit(EXIT_FAILURE);
-       }
-
-       exit(feof(stdin) ? EXIT_SUCCESS : EXIT_FAILURE);
-}