diff options
440 files changed, 19719 insertions, 0 deletions
diff --git a/.svn/README.txt b/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/.svn/empty-file b/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/.svn/empty-file diff --git a/.svn/entries b/.svn/entries new file mode 100644 index 0000000..bdb30d9 --- /dev/null +++ b/.svn/entries @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + name="Makefiles" + kind="dir"/> +<entry + name="tools" + kind="dir"/> +<entry + name="perl" + kind="dir"/> +<entry + name="tests" + kind="dir"/> +<entry + name="include" + kind="dir"/> +<entry + name="server" + kind="dir"/> +<entry + name="common" + kind="dir"/> +<entry + name="libconfig" + kind="dir"/> +<entry + committed-rev="1" + name="Makefile" + text-time="2005-12-24T00:01:05.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="9e09fbef2c041c0f2e0f56e0429a901c" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:01:03.000000Z"/> +<entry + name="client" + kind="dir"/> +</wc-entries> diff --git a/.svn/format b/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/.svn/format @@ -0,0 +1 @@ +4 diff --git a/.svn/prop-base/Makefile.svn-base b/.svn/prop-base/Makefile.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/.svn/prop-base/Makefile.svn-base @@ -0,0 +1 @@ +END diff --git a/.svn/props/Makefile.svn-work b/.svn/props/Makefile.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/.svn/props/Makefile.svn-work @@ -0,0 +1 @@ +END diff --git a/.svn/text-base/Makefile.svn-base b/.svn/text-base/Makefile.svn-base new file mode 100644 index 0000000..02eab92 --- /dev/null +++ b/.svn/text-base/Makefile.svn-base @@ -0,0 +1,10 @@ +# $Id: Makefile,v 1.1.1.1 2000/02/16 23:32:47 shmit Exp $ +# +# Do not edit this file. Edit the files in Makefiles instead. +# + +all: + @tools/build ${MAKE} $@ + +.DEFAULT: + @tools/build ${MAKE} $@ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..02eab92 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +# $Id: Makefile,v 1.1.1.1 2000/02/16 23:32:47 shmit Exp $ +# +# Do not edit this file. Edit the files in Makefiles instead. +# + +all: + @tools/build ${MAKE} $@ + +.DEFAULT: + @tools/build ${MAKE} $@ diff --git a/Makefiles/.svn/README.txt b/Makefiles/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/Makefiles/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/Makefiles/.svn/empty-file b/Makefiles/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Makefiles/.svn/empty-file diff --git a/Makefiles/.svn/entries b/Makefiles/.svn/entries new file mode 100644 index 0000000..46786c3 --- /dev/null +++ b/Makefiles/.svn/entries @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk/Makefiles" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + committed-rev="1" + name="build" + text-time="2005-12-24T00:00:40.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="01035c5b5538c67671bde47d4f0fa2e8" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:38.000000Z"/> +<entry + name="os" + kind="dir"/> +<entry + committed-rev="1" + name="config" + text-time="2005-12-24T00:00:40.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="89fb3d48473f6edb3478d3534c5b0299" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:40.000000Z"/> +</wc-entries> diff --git a/Makefiles/.svn/format b/Makefiles/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/Makefiles/.svn/format @@ -0,0 +1 @@ +4 diff --git a/Makefiles/.svn/prop-base/build.svn-base b/Makefiles/.svn/prop-base/build.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/.svn/prop-base/build.svn-base @@ -0,0 +1 @@ +END diff --git a/Makefiles/.svn/prop-base/config.svn-base b/Makefiles/.svn/prop-base/config.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/.svn/prop-base/config.svn-base @@ -0,0 +1 @@ +END diff --git a/Makefiles/.svn/props/build.svn-work b/Makefiles/.svn/props/build.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/.svn/props/build.svn-work @@ -0,0 +1 @@ +END diff --git a/Makefiles/.svn/props/config.svn-work b/Makefiles/.svn/props/config.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/.svn/props/config.svn-work @@ -0,0 +1 @@ +END diff --git a/Makefiles/.svn/text-base/build.svn-base b/Makefiles/.svn/text-base/build.svn-base new file mode 100644 index 0000000..61c6c64 --- /dev/null +++ b/Makefiles/.svn/text-base/build.svn-base @@ -0,0 +1,84 @@ +# $Id: build,v 1.22 2001/10/29 11:22:05 shmit Exp $ +# +# Don't do configuration in this file! Edit Makefile.config instead. +# + +CFLAGS= ${DEBUGFLAGS} ${PROFFLAGS} ${OSFLAGS} ${OPTFLAGS} \ + ${THREADFLAGS} ${PATH_DEFS} -I${TOPDIR}/include \ + ${OBJCINC} ${MYSQL_INCS} ${DB_DEFS} -D_REENTRANT \ + -D_THREAD_SAFE + +LIBS= ${OSLIBS} -lobjc + +# Path settings. +PATH_DEFS= -DDATADIR=\"${DATADIR}\" + +# MySQL settings. +MYSQL_LIBS= ${RPATH} ${MYSQL_LIBDIR} -L${MYSQL_LIBDIR} -lmysqlclient -lm +MYSQL_INCS= -I${MYSQL_INCDIR} +DB_DEFS= -DDBUSER=${DBUSER} -DDBPASS=${DBPASS} \ + -DDBHOST=${DBHOST} -DDBNAME=${DBNAME} \ + -DDBTBL=${DBTBL} -DDBSELECT=${DBSELECT} + +BINS= tests/getnast tests/updnast tests/statnast tests/killnast +SBINS= server/nastd +INCS= include/nastd.h +ASSLIBS= client/libnast.a client/libnast_r.a + +.SUFFIXES: .c .m .o + +.PHONY: common libconfig server client tests perl + +all: server client tests perl + +install: all + mkdir -p ${BINDIR} ${SBINDIR} ${INCDIR} ${LIBDIR} ${DATADIR} + ${INSTALL} -c -m 755 ${BINS} ${BINDIR} + ${INSTALL} -c -m 755 ${SBINS} ${SBINDIR} + ${INSTALL} -c -m 644 ${INCS} ${INCDIR} + ${INSTALL} -c -m 644 ${ASSLIBS} ${LIBDIR} + @(cd perl && ./build ${MAKE} ${PERL} install) + +server: common libconfig + @(echo "===> server" && cd server && ${MAKE}) + +client: common + @(echo "===> client" && cd client && ${MAKE}) + +tests: common + @(echo "===> tests" && cd tests && ${MAKE}) + +common: + @(echo "===> common" && cd common && ${MAKE}) + +libconfig: + @(echo "===> libconfig" && cd libconfig && ${MAKE}) + +perl: + @(echo "===> perl" && cd perl && ./build ${MAKE} ${PERL}) + +clean: + @(cd ${TOPDIR} && ${MAKE} realclean) + +realclean: + rm -f common/*.o common/*.a client/*.o server/*.o + rm -f tests/*.o tests/getnast + rm -f perl/Makefile perl/NASTD.c perl/NASTD.bs perl/*.o + rm -rf perl/blib + +.c.o: + ${CC} ${CFLAGS} -c $< + +.m.o: + ${CC} ${CFLAGS} -c $< + +.c.So: + ${CC} ${CFLAGS} -fpic -DPIC -o $@ -c $< + +MKDIR?= Makefiles +TOPDIR= ${MKDIR}/.. +MKLIB= ${TOPDIR}/tools/makelib +MKMODLIST= ${TOPDIR}/tools/mkmodlist + +include ${MKDIR}/config +include ${MKDIR}/os/target diff --git a/Makefiles/.svn/text-base/config.svn-base b/Makefiles/.svn/text-base/config.svn-base new file mode 100644 index 0000000..813b4ca --- /dev/null +++ b/Makefiles/.svn/text-base/config.svn-base @@ -0,0 +1,44 @@ +# $Id: config,v 1.24 2001/11/09 15:54:37 shmit Exp $ +# +# Add -DSHADOW to OPTFLAGS if you want to use have shadow passwords. + +# Where to place things. +#PREFIX= /opt +PREFIX= /home/shmit +BINDIR= ${PREFIX}/bin +SBINDIR= ${PREFIX}/sbin +DATADIR= ${PREFIX}/libdata/nast +INCDIR= ${PREFIX}/include +LIBDIR= ${PREFIX}/lib +SRCDIR= . + +# Set this to NO if you don't want the perl library built. +PERL= NO + +# Purify options +#PURIFY= purify + +# MySQL library and include file location. +MYSQL_INCDIR= /local/include +MYSQL_LIBDIR= /local/lib + +# Generic Database configuration. +DBUSER= \"root\" +DBPASS= NULL +#DBPASS= \"h4x0rZ,uhb0und!\" +DBHOST= NULL +#DBHOST= \"mysql.dev.rcn.net\" +DBNAME= \"password\" +DBTBL= \"master\" +DBSELECT= "\"SELECT %s FROM %s WHERE %s='%s'"\" + +# Location of Objective C include files. +OBJCINC= -I/local/include/objc + +# Debugging flags. +DEBUGFLAGS= -g -DTEST -DVERBOSE -Wall -Werror +#DEBUGFLAGS= -DTEST -DVERBOSE +#PROFFLAGS= -pg + +# Optimization flags to the C compiler. +#OPTFLAGS= -O diff --git a/Makefiles/build b/Makefiles/build new file mode 100644 index 0000000..61c6c64 --- /dev/null +++ b/Makefiles/build @@ -0,0 +1,84 @@ +# $Id: build,v 1.22 2001/10/29 11:22:05 shmit Exp $ +# +# Don't do configuration in this file! Edit Makefile.config instead. +# + +CFLAGS= ${DEBUGFLAGS} ${PROFFLAGS} ${OSFLAGS} ${OPTFLAGS} \ + ${THREADFLAGS} ${PATH_DEFS} -I${TOPDIR}/include \ + ${OBJCINC} ${MYSQL_INCS} ${DB_DEFS} -D_REENTRANT \ + -D_THREAD_SAFE + +LIBS= ${OSLIBS} -lobjc + +# Path settings. +PATH_DEFS= -DDATADIR=\"${DATADIR}\" + +# MySQL settings. +MYSQL_LIBS= ${RPATH} ${MYSQL_LIBDIR} -L${MYSQL_LIBDIR} -lmysqlclient -lm +MYSQL_INCS= -I${MYSQL_INCDIR} +DB_DEFS= -DDBUSER=${DBUSER} -DDBPASS=${DBPASS} \ + -DDBHOST=${DBHOST} -DDBNAME=${DBNAME} \ + -DDBTBL=${DBTBL} -DDBSELECT=${DBSELECT} + +BINS= tests/getnast tests/updnast tests/statnast tests/killnast +SBINS= server/nastd +INCS= include/nastd.h +ASSLIBS= client/libnast.a client/libnast_r.a + +.SUFFIXES: .c .m .o + +.PHONY: common libconfig server client tests perl + +all: server client tests perl + +install: all + mkdir -p ${BINDIR} ${SBINDIR} ${INCDIR} ${LIBDIR} ${DATADIR} + ${INSTALL} -c -m 755 ${BINS} ${BINDIR} + ${INSTALL} -c -m 755 ${SBINS} ${SBINDIR} + ${INSTALL} -c -m 644 ${INCS} ${INCDIR} + ${INSTALL} -c -m 644 ${ASSLIBS} ${LIBDIR} + @(cd perl && ./build ${MAKE} ${PERL} install) + +server: common libconfig + @(echo "===> server" && cd server && ${MAKE}) + +client: common + @(echo "===> client" && cd client && ${MAKE}) + +tests: common + @(echo "===> tests" && cd tests && ${MAKE}) + +common: + @(echo "===> common" && cd common && ${MAKE}) + +libconfig: + @(echo "===> libconfig" && cd libconfig && ${MAKE}) + +perl: + @(echo "===> perl" && cd perl && ./build ${MAKE} ${PERL}) + +clean: + @(cd ${TOPDIR} && ${MAKE} realclean) + +realclean: + rm -f common/*.o common/*.a client/*.o server/*.o + rm -f tests/*.o tests/getnast + rm -f perl/Makefile perl/NASTD.c perl/NASTD.bs perl/*.o + rm -rf perl/blib + +.c.o: + ${CC} ${CFLAGS} -c $< + +.m.o: + ${CC} ${CFLAGS} -c $< + +.c.So: + ${CC} ${CFLAGS} -fpic -DPIC -o $@ -c $< + +MKDIR?= Makefiles +TOPDIR= ${MKDIR}/.. +MKLIB= ${TOPDIR}/tools/makelib +MKMODLIST= ${TOPDIR}/tools/mkmodlist + +include ${MKDIR}/config +include ${MKDIR}/os/target diff --git a/Makefiles/config b/Makefiles/config new file mode 100644 index 0000000..813b4ca --- /dev/null +++ b/Makefiles/config @@ -0,0 +1,44 @@ +# $Id: config,v 1.24 2001/11/09 15:54:37 shmit Exp $ +# +# Add -DSHADOW to OPTFLAGS if you want to use have shadow passwords. + +# Where to place things. +#PREFIX= /opt +PREFIX= /home/shmit +BINDIR= ${PREFIX}/bin +SBINDIR= ${PREFIX}/sbin +DATADIR= ${PREFIX}/libdata/nast +INCDIR= ${PREFIX}/include +LIBDIR= ${PREFIX}/lib +SRCDIR= . + +# Set this to NO if you don't want the perl library built. +PERL= NO + +# Purify options +#PURIFY= purify + +# MySQL library and include file location. +MYSQL_INCDIR= /local/include +MYSQL_LIBDIR= /local/lib + +# Generic Database configuration. +DBUSER= \"root\" +DBPASS= NULL +#DBPASS= \"h4x0rZ,uhb0und!\" +DBHOST= NULL +#DBHOST= \"mysql.dev.rcn.net\" +DBNAME= \"password\" +DBTBL= \"master\" +DBSELECT= "\"SELECT %s FROM %s WHERE %s='%s'"\" + +# Location of Objective C include files. +OBJCINC= -I/local/include/objc + +# Debugging flags. +DEBUGFLAGS= -g -DTEST -DVERBOSE -Wall -Werror +#DEBUGFLAGS= -DTEST -DVERBOSE +#PROFFLAGS= -pg + +# Optimization flags to the C compiler. +#OPTFLAGS= -O diff --git a/Makefiles/os/.cvsignore b/Makefiles/os/.cvsignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/Makefiles/os/.cvsignore @@ -0,0 +1 @@ +target diff --git a/Makefiles/os/.svn/README.txt b/Makefiles/os/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/Makefiles/os/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/Makefiles/os/.svn/empty-file b/Makefiles/os/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Makefiles/os/.svn/empty-file diff --git a/Makefiles/os/.svn/entries b/Makefiles/os/.svn/entries new file mode 100644 index 0000000..c1657db --- /dev/null +++ b/Makefiles/os/.svn/entries @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk/Makefiles/os" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + committed-rev="1" + name="linux" + text-time="2005-12-24T00:00:39.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="33118b2ed9fdd39180d2faf716511b64" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:39.000000Z"/> +<entry + committed-rev="1" + name="sunos" + text-time="2005-12-24T00:00:39.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="d286f2b75d1fdf0873dde83f057f9cac" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:39.000000Z"/> +<entry + committed-rev="1" + name="freebsd" + text-time="2005-12-24T00:00:40.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="152b5b3eb3560dc62bc2f51a843bfe88" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:39.000000Z"/> +<entry + committed-rev="1" + name="freebsd2" + text-time="2005-12-24T00:00:40.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="4cd08c472fa6a082e6432881601d1f97" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:39.000000Z"/> +<entry + committed-rev="1" + name="solaris" + text-time="2005-12-24T00:00:40.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="5ee16c2cac3da4723e2fefcf1dfac6b3" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:39.000000Z"/> +<entry + committed-rev="1" + name=".cvsignore" + text-time="2005-12-24T00:00:40.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="80fb1dd0b20823f1d83e10d25840e2e4" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:39.000000Z"/> +</wc-entries> diff --git a/Makefiles/os/.svn/format b/Makefiles/os/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/Makefiles/os/.svn/format @@ -0,0 +1 @@ +4 diff --git a/Makefiles/os/.svn/prop-base/.cvsignore.svn-base b/Makefiles/os/.svn/prop-base/.cvsignore.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/prop-base/.cvsignore.svn-base @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/prop-base/freebsd.svn-base b/Makefiles/os/.svn/prop-base/freebsd.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/prop-base/freebsd.svn-base @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/prop-base/freebsd2.svn-base b/Makefiles/os/.svn/prop-base/freebsd2.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/prop-base/freebsd2.svn-base @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/prop-base/linux.svn-base b/Makefiles/os/.svn/prop-base/linux.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/prop-base/linux.svn-base @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/prop-base/solaris.svn-base b/Makefiles/os/.svn/prop-base/solaris.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/prop-base/solaris.svn-base @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/prop-base/sunos.svn-base b/Makefiles/os/.svn/prop-base/sunos.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/prop-base/sunos.svn-base @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/props/.cvsignore.svn-work b/Makefiles/os/.svn/props/.cvsignore.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/props/.cvsignore.svn-work @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/props/freebsd.svn-work b/Makefiles/os/.svn/props/freebsd.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/props/freebsd.svn-work @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/props/freebsd2.svn-work b/Makefiles/os/.svn/props/freebsd2.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/props/freebsd2.svn-work @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/props/linux.svn-work b/Makefiles/os/.svn/props/linux.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/props/linux.svn-work @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/props/solaris.svn-work b/Makefiles/os/.svn/props/solaris.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/props/solaris.svn-work @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/props/sunos.svn-work b/Makefiles/os/.svn/props/sunos.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/Makefiles/os/.svn/props/sunos.svn-work @@ -0,0 +1 @@ +END diff --git a/Makefiles/os/.svn/text-base/.cvsignore.svn-base b/Makefiles/os/.svn/text-base/.cvsignore.svn-base new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/Makefiles/os/.svn/text-base/.cvsignore.svn-base @@ -0,0 +1 @@ +target diff --git a/Makefiles/os/.svn/text-base/freebsd.svn-base b/Makefiles/os/.svn/text-base/freebsd.svn-base new file mode 100644 index 0000000..7eb2e17 --- /dev/null +++ b/Makefiles/os/.svn/text-base/freebsd.svn-base @@ -0,0 +1,7 @@ +# $Id: freebsd,v 1.1.1.1 2000/02/16 23:32:48 shmit Exp $ + +CC= gcc -pthread +INSTALL= install + +OSFLAGS= -DOS_FREEBSD -DFREEBSD_3 +OSLIBS= -lcrypt -lutil diff --git a/Makefiles/os/.svn/text-base/freebsd2.svn-base b/Makefiles/os/.svn/text-base/freebsd2.svn-base new file mode 100644 index 0000000..387db8e --- /dev/null +++ b/Makefiles/os/.svn/text-base/freebsd2.svn-base @@ -0,0 +1,7 @@ +# $Id: freebsd2,v 1.1.1.1 2000/02/16 23:32:48 shmit Exp $ + +CC= gcc +INSTALL= install + +OSFLAGS= -DOS_FREEBSD -DFREEBSD_2 +OSLIBS= -lcrypt -lutil diff --git a/Makefiles/os/.svn/text-base/linux.svn-base b/Makefiles/os/.svn/text-base/linux.svn-base new file mode 100644 index 0000000..2f453ef --- /dev/null +++ b/Makefiles/os/.svn/text-base/linux.svn-base @@ -0,0 +1,8 @@ +# $Id: linux,v 1.3 2000/03/21 19:25:17 shmit Exp $ + +CC= gcc +INSTALL= install +RPATH= -L + +OSFLAGS= -DOS_LINUX +OSLIBS= -lpthread diff --git a/Makefiles/os/.svn/text-base/solaris.svn-base b/Makefiles/os/.svn/text-base/solaris.svn-base new file mode 100644 index 0000000..ca7834d --- /dev/null +++ b/Makefiles/os/.svn/text-base/solaris.svn-base @@ -0,0 +1,8 @@ +# $Id: solaris,v 1.2 2000/03/21 19:22:51 shmit Exp $ + +CC= gcc +INSTALL= /usr/ucb/install +RPATH= -R + +OSFLAGS= -DOS_SOLARIS -D_POSIX_PTHREAD_SEMANTICS +OSLIBS= -lpthread -lnsl -lsocket -lposix4 -ldl diff --git a/Makefiles/os/.svn/text-base/sunos.svn-base b/Makefiles/os/.svn/text-base/sunos.svn-base new file mode 100644 index 0000000..93324f7 --- /dev/null +++ b/Makefiles/os/.svn/text-base/sunos.svn-base @@ -0,0 +1,7 @@ +# $Id: sunos,v 1.1.1.1 2000/02/16 23:32:47 shmit Exp $ + +CC= gcc +INSTALL= /usr/ucb/install + +OSFLAGS= -DOS_SUNOS +OSLIBS= -lnsl -lsocket diff --git a/Makefiles/os/freebsd b/Makefiles/os/freebsd new file mode 100644 index 0000000..7eb2e17 --- /dev/null +++ b/Makefiles/os/freebsd @@ -0,0 +1,7 @@ +# $Id: freebsd,v 1.1.1.1 2000/02/16 23:32:48 shmit Exp $ + +CC= gcc -pthread +INSTALL= install + +OSFLAGS= -DOS_FREEBSD -DFREEBSD_3 +OSLIBS= -lcrypt -lutil diff --git a/Makefiles/os/freebsd2 b/Makefiles/os/freebsd2 new file mode 100644 index 0000000..387db8e --- /dev/null +++ b/Makefiles/os/freebsd2 @@ -0,0 +1,7 @@ +# $Id: freebsd2,v 1.1.1.1 2000/02/16 23:32:48 shmit Exp $ + +CC= gcc +INSTALL= install + +OSFLAGS= -DOS_FREEBSD -DFREEBSD_2 +OSLIBS= -lcrypt -lutil diff --git a/Makefiles/os/linux b/Makefiles/os/linux new file mode 100644 index 0000000..2f453ef --- /dev/null +++ b/Makefiles/os/linux @@ -0,0 +1,8 @@ +# $Id: linux,v 1.3 2000/03/21 19:25:17 shmit Exp $ + +CC= gcc +INSTALL= install +RPATH= -L + +OSFLAGS= -DOS_LINUX +OSLIBS= -lpthread diff --git a/Makefiles/os/solaris b/Makefiles/os/solaris new file mode 100644 index 0000000..ca7834d --- /dev/null +++ b/Makefiles/os/solaris @@ -0,0 +1,8 @@ +# $Id: solaris,v 1.2 2000/03/21 19:22:51 shmit Exp $ + +CC= gcc +INSTALL= /usr/ucb/install +RPATH= -R + +OSFLAGS= -DOS_SOLARIS -D_POSIX_PTHREAD_SEMANTICS +OSLIBS= -lpthread -lnsl -lsocket -lposix4 -ldl diff --git a/Makefiles/os/sunos b/Makefiles/os/sunos new file mode 100644 index 0000000..93324f7 --- /dev/null +++ b/Makefiles/os/sunos @@ -0,0 +1,7 @@ +# $Id: sunos,v 1.1.1.1 2000/02/16 23:32:47 shmit Exp $ + +CC= gcc +INSTALL= /usr/ucb/install + +OSFLAGS= -DOS_SUNOS +OSLIBS= -lnsl -lsocket diff --git a/client/.cvsignore b/client/.cvsignore new file mode 100644 index 0000000..35f79a6 --- /dev/null +++ b/client/.cvsignore @@ -0,0 +1,7 @@ +.pure +*.o +*.so +*.a +*.core +*.gmon +tags diff --git a/client/.pure b/client/.pure new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/client/.pure diff --git a/client/.svn/README.txt b/client/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/client/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/client/.svn/empty-file b/client/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/client/.svn/empty-file diff --git a/client/.svn/entries b/client/.svn/entries new file mode 100644 index 0000000..273f9c8 --- /dev/null +++ b/client/.svn/entries @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk/client" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + committed-rev="1" + name="nastapi.c" + text-time="2005-12-24T00:01:04.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="58742753ba1da3456bab621d9ce1b743" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:01:03.000000Z"/> +<entry + committed-rev="1" + name="thread.c" + text-time="2005-12-24T00:01:04.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="b2c15aef2f6f15a0c7d005692aab8988" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:01:03.000000Z"/> +<entry + committed-rev="1" + name=".pure" + text-time="2005-12-24T00:01:04.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="d41d8cd98f00b204e9800998ecf8427e" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:01:04.000000Z"/> +<entry + committed-rev="1" + name=".cvsignore" + text-time="2005-12-24T00:01:04.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="d3ab4aa9b2ce78dcf3467cf1a8ddb6d1" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:01:04.000000Z"/> +<entry + committed-rev="1" + name="Makefile" + text-time="2005-12-24T00:01:04.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="e8640e9f9f184a80e9bed5d894578c58" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:01:04.000000Z"/> +<entry + committed-rev="1" + name="thread.h" + text-time="2005-12-24T00:01:04.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="a548e3157e8dba41d2ab2bb83a20aafe" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:01:04.000000Z"/> +</wc-entries> diff --git a/client/.svn/format b/client/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/client/.svn/format @@ -0,0 +1 @@ +4 diff --git a/client/.svn/prop-base/.cvsignore.svn-base b/client/.svn/prop-base/.cvsignore.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/prop-base/.cvsignore.svn-base @@ -0,0 +1 @@ +END diff --git a/client/.svn/prop-base/.pure.svn-base b/client/.svn/prop-base/.pure.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/prop-base/.pure.svn-base @@ -0,0 +1 @@ +END diff --git a/client/.svn/prop-base/Makefile.svn-base b/client/.svn/prop-base/Makefile.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/prop-base/Makefile.svn-base @@ -0,0 +1 @@ +END diff --git a/client/.svn/prop-base/nastapi.c.svn-base b/client/.svn/prop-base/nastapi.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/prop-base/nastapi.c.svn-base @@ -0,0 +1 @@ +END diff --git a/client/.svn/prop-base/thread.c.svn-base b/client/.svn/prop-base/thread.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/prop-base/thread.c.svn-base @@ -0,0 +1 @@ +END diff --git a/client/.svn/prop-base/thread.h.svn-base b/client/.svn/prop-base/thread.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/prop-base/thread.h.svn-base @@ -0,0 +1 @@ +END diff --git a/client/.svn/props/.cvsignore.svn-work b/client/.svn/props/.cvsignore.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/props/.cvsignore.svn-work @@ -0,0 +1 @@ +END diff --git a/client/.svn/props/.pure.svn-work b/client/.svn/props/.pure.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/props/.pure.svn-work @@ -0,0 +1 @@ +END diff --git a/client/.svn/props/Makefile.svn-work b/client/.svn/props/Makefile.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/props/Makefile.svn-work @@ -0,0 +1 @@ +END diff --git a/client/.svn/props/nastapi.c.svn-work b/client/.svn/props/nastapi.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/props/nastapi.c.svn-work @@ -0,0 +1 @@ +END diff --git a/client/.svn/props/thread.c.svn-work b/client/.svn/props/thread.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/props/thread.c.svn-work @@ -0,0 +1 @@ +END diff --git a/client/.svn/props/thread.h.svn-work b/client/.svn/props/thread.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/client/.svn/props/thread.h.svn-work @@ -0,0 +1 @@ +END diff --git a/client/.svn/text-base/.cvsignore.svn-base b/client/.svn/text-base/.cvsignore.svn-base new file mode 100644 index 0000000..35f79a6 --- /dev/null +++ b/client/.svn/text-base/.cvsignore.svn-base @@ -0,0 +1,7 @@ +.pure +*.o +*.so +*.a +*.core +*.gmon +tags diff --git a/client/.svn/text-base/.pure.svn-base b/client/.svn/text-base/.pure.svn-base new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/client/.svn/text-base/.pure.svn-base diff --git a/client/.svn/text-base/Makefile.svn-base b/client/.svn/text-base/Makefile.svn-base new file mode 100644 index 0000000..e92feed --- /dev/null +++ b/client/.svn/text-base/Makefile.svn-base @@ -0,0 +1,26 @@ +# $Id: Makefile,v 1.10 2001/01/19 02:54:37 shmit Exp $ + +LIBOBJS= nastapi.o thread.o + +all-lib: + @rm -f *.o + @make "THREADFLAGS=-UTHREADSAFECLIENT" libnast.a + @rm -f *.o + @make "THREADFLAGS=-DTHREADSAFECLIENT" libnast_r.a + +libnast.a: ${LIBOBJS} + ar r $@ ${LIBOBJS} + ranlib $@ + +libnast_r.a: ${LIBOBJS} + ar r $@ ${LIBOBJS} + ranlib $@ + +# +# Dependencies +# +nastapi.o: ../include/nastd.h ../include/nastipc.h thread.h +thread.o: thread.h + +MKDIR= ../Makefiles +include ${MKDIR}/build diff --git a/client/.svn/text-base/nastapi.c.svn-base b/client/.svn/text-base/nastapi.c.svn-base new file mode 100644 index 0000000..3e5a3b9 --- /dev/null +++ b/client/.svn/text-base/nastapi.c.svn-base @@ -0,0 +1,885 @@ +#include "conf.h" +#include "nastd.h" +#include "nastipc.h" +#include "thread.h" + +#include <errno.h> +#include <thread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <sys/un.h> +#include <signal.h> +#include <unistd.h> + +RCSID("$Id: nastapi.c,v 1.13 2001/10/29 11:17:11 shmit Exp $"); + +char *nast_errmsgs[] = { + "No errors", + "The NASTD server has gone away", + "Couldn't allocate enough memory", + "Server response is unknown", + "Connection to server timed out", + "Unknown option returned", + NULL +}; + +static nast_string_t * +nast_string_new(int slen, const char *data) +{ + nast_string_t *tmp; + + tmp = malloc(sizeof(nast_string_t)); + if (tmp == NULL) + return NULL; + + tmp->strdata = malloc((slen+1) * sizeof(char *)); + if (tmp == NULL) + return NULL; + memcpy(tmp->strdata, data, slen); + tmp->strdata[slen] = '\0'; + tmp->strlen = slen; + + return tmp; +} + +static void +nast_string_delete(nast_string_t *string) +{ + string->strlen = 0; + free(string->strdata); + string->strdata = NULL; + free(string); +} + +nast_array * +nast_array_new() +{ + nast_array *aa; + + aa = malloc(sizeof(nast_array)); + if (aa == NULL) + return NULL; + + aa->nitems = 0; + aa->items = NULL; + return aa; +} + +int +nast_array_add(nast_array *array, short len, const char *data) +{ + const int GRANULARITY = 10; + + if (array->nitems % GRANULARITY == 0) { + nast_string_t **tmp; + tmp = realloc(array->items, sizeof(char *) * + (GRANULARITY + array->nitems)); + if (tmp == NULL) + return -1; + array->items = tmp; + } + array->nitems++; + + array->items[array->nitems-1] = nast_string_new(len, data); + if (array->items[array->nitems-1] == NULL) + return -1; + + return 0; +} + +void +nast_array_delete(nast_array *array) +{ + nast_free_result(array); +} + +static nast_response * +response_new() +{ + nast_response *tmp; + + tmp = malloc(sizeof(nast_response)); + if (tmp == NULL) + return NULL; + + tmp->buffer = NULL; + tmp->bufflen = 0; + tmp->errcode = NAST_OK; + tmp->errmsg = NULL; + tmp->reqid = -1; + + return tmp; +} + +static nast_response * +getmyresponse(nasth *s, unsigned short reqid) +{ + if (s->nthreads < reqid) + return NULL; + + return s->responses[reqid-1]; +} + +static void +nast_set_error(nasth *s, unsigned short reqid, errcodes code) +{ + nast_response *ar; + + ar = getmyresponse(s, reqid); + if (ar == NULL) + return; + + ar->errcode = code; +} + +static int +grow_responses(nasth *s, unsigned short maxitems) +{ + nast_response **tmp_resp; + int i; + + if (s->nthreads >= maxitems) + return 0; + + tmp_resp = realloc(s->responses, maxitems * sizeof(nast_response *)); + if (tmp_resp == NULL) + return -1; + + s->responses = tmp_resp; + for (i = s->nthreads; i < maxitems; i++) { + s->responses[i] = response_new(); + if (s->responses[i] == NULL) + return -1; + } + + s->nthreads = maxitems; + return 0; +} + +static nast_array * +build_result(nasth *s, const char *buff, short bufflen) +{ + nast_array *aa; + const char *s_p, *e_p; + short l; + + aa = nast_array_new(); + if (aa == NULL) { + nast_set_error(s, thread_id(), NAST_NOMEM); + return NULL; + } + + /* Parse the buff into an array. */ + l = 0; + aa->nitems = 0; + aa->items = NULL; + s_p = buff+l; + for (e_p = s_p; e_p <= buff+bufflen; e_p++) { + if (e_p == buff+bufflen || *e_p == NASTSEP) { + if (nast_array_add(aa, e_p - s_p, s_p) == -1) { + nast_set_error(s, thread_id(), NAST_NOMEM); + return NULL; + } + s_p = e_p + 1; + } + } + + return aa; +} + +static int +addresponse(nasth *s, unsigned short reqid, char *buffer, short len) +{ + nast_response *ar; + + switch (buffer[0]) { + case NASTOK: + nast_set_error(s, reqid, NAST_OK); + break; + case NASTERR: + nast_set_error(s, reqid, NAST_SERVER_ERR); + break; + default: + nast_set_error(s, reqid, NAST_UNKNOWN_RESPONSE); + } + + ar = getmyresponse(s, reqid); + if (ar == NULL) { + /* + * Somehow we got a response for something we didn't + * request. + */ + return -1; + } + + ar->reqid = reqid; + ar->buffer = malloc(len-1); + if (ar->buffer == NULL) { + nast_set_error(s, reqid, NAST_NOMEM); + return -1; + } + memcpy(ar->buffer, buffer+1, len-1); + ar->bufflen = len-1; + return 0; +} + +static void +delresponse(nasth *s, unsigned short reqid) +{ + nast_response *ar; + + ar = getmyresponse(s, reqid); + if (ar == NULL) + return; + + ar->reqid = -1; + if (ar->buffer) + free(ar->buffer); + ar->bufflen = 0; +} + +static int +checkresponse(nasth *s, unsigned short reqid) +{ + nast_response *ar; + + if (reqid > s->nthreads) + return -1; + + ar = getmyresponse(s, reqid); + if (ar == NULL || (short)ar->reqid == -1) + return -1; + + return 0; +} + +static int +sendcmd(nasth *s, const char *buff, short len) +{ + ssize_t wrote; + + /* Make sure there's room in the response array. */ + if (grow_responses(s, thread_id()) == -1) { + /* + * XXX: This is a fatal error. + * Find some better way to handle this. + */ + exit(1); + } + + /* If we're sending a command, make sure we get rid of old data. */ + delresponse(s, thread_id()); + + /* Send the command. */ + wrote = 0; + while (wrote < len) { + ssize_t rc; + + rc = write(s->socket, buff + wrote, len - wrote); + if (rc == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + nast_set_error(s, thread_id(), NAST_SERVER_GONE); + return -1; + } + wrote += rc; + } + + /* Check status. */ + return 0; +} + +static int +getresponse(nasth *s) +{ + char buffer[1024]; + nast_response *ar; + int ntries, rc; + unsigned short tid; + short nbytes; + + ntries = 0; + tid = thread_id(); +reread: + _nast_mutex_lock(s->lock); + + /* + * See if we already have the response from another thread which + * may have found it first. + */ + rc = checkresponse(s, tid); + if (rc == 0) { + _nast_mutex_unlock(s->lock); + } else { + /* Not in the already read stuff, check the network. */ + char *p; + short bufflen; + unsigned short reqid; + fd_set readfds; + struct timeval timeout; + + FD_ZERO(&readfds); + FD_SET(s->socket, &readfds); + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + switch(select(s->socket+1, &readfds, NULL, NULL, &timeout)) { + case -1: + _nast_mutex_unlock(s->lock); + nast_set_error(s, tid, NAST_SERVER_GONE); + return -1; + case 0: + /* Timeout expired. */ + _nast_mutex_unlock(s->lock); + if (ntries++ < 50) + goto reread; + nast_set_error(s, tid, NAST_TIMEDOUT); + return -1; + } + nbytes = recv(s->socket, buffer, sizeof(buffer), 0); + if (nbytes == -1) { + _nast_mutex_unlock(s->lock); + nast_set_error(s, tid, NAST_SERVER_GONE); + return -1; + } else if (nbytes == 0) { + /* No response from server. That's bad. Terminate. */ + _nast_mutex_unlock(s->lock); + nast_set_error(s, tid, NAST_SERVER_GONE); + return -1; + } else if (nbytes < + sizeof(bufflen) + sizeof(reqid) + sizeof(char)) { + /* Response is too short. */ + _nast_mutex_unlock(s->lock); + nast_set_error(s, tid, NAST_UNKNOWN_RESPONSE); + return -1; + } + + for (p = buffer; p < buffer+nbytes; p += bufflen) { + int l; + + memcpy(&bufflen, p, sizeof(bufflen)); + bufflen = ntohs(bufflen); + l = sizeof(bufflen); + + /* Sanity check, just in case data gets munged. */ + if (bufflen <= 0 || bufflen > nbytes) { + _nast_mutex_unlock(s->lock); + nast_set_error(s, tid, NAST_UNKNOWN_RESPONSE); + return -1; + } + + memcpy(&reqid, p+l, sizeof(reqid)); + reqid = ntohs(reqid); + l += sizeof(reqid); + + /* Save this response on the response array. */ + addresponse(s, reqid, p+l, bufflen-l); + } + /* Check the response array to see if we got our response. */ + _nast_mutex_unlock(s->lock); + goto reread; + } + + ar = getmyresponse(s, tid); + if (ar->errcode == NAST_OK) + return 0; + else + return -1; +} + +nasth * +nast_sphincter_new(const char *sock_path) +{ + nasth *tmp_h; + struct sockaddr_un sunix; + int rc; + + tmp_h = malloc(sizeof(nasth)); + if (tmp_h == NULL) { + fprintf(stderr, + "ERROR: Couldn't make space for sphincter: %s.\n", + strerror(errno)); + return NULL; + } + + tmp_h->nthreads = 0; + tmp_h->responses = NULL; + + tmp_h->lock = malloc(sizeof(_nast_mutex_t)); + if (tmp_h->lock == NULL) { + fprintf(stderr, + "ERROR: Couldn't create NAST lock: %s.\n", + strerror(errno)); + nast_sphincter_close(tmp_h); + return NULL; + } + rc = _nast_mutex_new(tmp_h->lock); + if (rc) { + fprintf(stderr, + "ERROR: Couldn't initialise NAST lock: %s.\n", + strerror(rc)); + nast_sphincter_close(tmp_h); + return NULL; + } + + tmp_h->socket = socket(AF_UNIX, SOCK_STREAM, 0); + if (tmp_h->socket == -1) { + fprintf(stderr, + "ERROR: Couldn't initialise socket: %s.\n", + strerror(errno)); + nast_sphincter_close(tmp_h); + return NULL; + } + + memset(&sunix, 0, sizeof(sunix)); + if (sock_path == NULL) + snprintf(sunix.sun_path, sizeof(sunix.sun_path), NASTHOLE); + else + strncpy(sunix.sun_path, sock_path, sizeof(sunix.sun_path)); + sunix.sun_family = AF_UNIX; + + if (connect(tmp_h->socket, (struct sockaddr *)&sunix, + sizeof(sunix)) == -1) { + fprintf(stderr, + "ERROR: Couldn't connect to server: %s.\n", + strerror(errno)); + nast_sphincter_close(tmp_h); + return NULL; + } + return tmp_h; +} + +void +nast_sphincter_close(nasth *s) +{ + int i; + + if (s == NULL) + return; + + s->nthreads = 0; + + if (s->lock != NULL) { + _nast_mutex_delete(s->lock); + free(s->lock); + s->lock = NULL; + } + + if (s->socket != -1) { + close(s->socket); + s->socket = -1; + } + + if (s->responses != NULL) { + for (i = 0; i < s->nthreads; i++) { + if (s->responses[i]->buffer != NULL) + free(s->responses[i]->buffer); + free(s->responses[i]); + s->responses[i] = NULL; + } + free(s->responses); + s->responses = NULL; + } + + free(s); +} + +nast_array * +nast_get_result(nasth *s) +{ + nast_response *ar; + + ar = getmyresponse(s, thread_id()); + if (ar == NULL) + return NULL; + + return build_result(s, ar->buffer, ar->bufflen); +} + +void +nast_free_result(nast_array *aa) +{ + int i; + + if (aa->items) { + for (i = 0; i < aa->nitems; i++) + nast_string_delete(aa->items[i]); + free(aa->items); + aa->items = NULL; + } + aa->nitems = 0; + free(aa); +} + +static int +add_reqid(char *buffer) +{ + unsigned short tid; + + tid = thread_id(); + memcpy(buffer, &htons(tid), sizeof(tid)); + + return sizeof(tid); +} + +int +nast_options_get(nasth *s, nast_options *opts) +{ + nast_array *aa; + char buffer[512]; + short bufflen, i; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't get options: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c", + NASTCMD, NASTOPTGET); + bufflen += 2 * sizeof(char); + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + if (getresponse(s) == -1) + return -1; + + /* Copy out results and free them. */ + aa = nast_get_result(s); + + if (aa->nitems != 1) { + nast_set_error(s, thread_id(), NAST_UNKNOWN_RESPONSE); + return -1; + } + + if (sizeof(buffer) < aa->items[0]->strlen) + bufflen = sizeof(buffer); + else + bufflen = aa->items[0]->strlen; + memcpy(buffer, aa->items[0]->strdata, bufflen); + nast_free_result(aa); + + /* Parse return into options. */ + for (i = 0; i < bufflen; i+=2) { + switch (buffer[i]) { + case OPTQCACHE: + if (buffer[i+1] == OPTFALSE) + opts->use_qcache = NASTFALSE; + else + opts->use_qcache = NASTTRUE; + break; + case OPTLOCALDB: + if (buffer[i+1] == OPTFALSE) + opts->use_localdb = NASTFALSE; + else + opts->use_localdb = NASTTRUE; + break; + case OPTFALLASYNC: + if (buffer[i+1] == OPTFALSE) + opts->fallthrough_async = NASTFALSE; + else + opts->fallthrough_async = NASTTRUE; + break; + case OPTALWAYSFALL: + if (buffer[i+1] == OPTFALSE) + opts->always_fallthrough = NASTFALSE; + else + opts->always_fallthrough = NASTTRUE; + break; + case OPTFAILONCE: + if (buffer[i+1] == OPTFALSE) + opts->fail_once = NASTFALSE; + else + opts->fail_once = NASTTRUE; + break; + case OPTNOFALLTHROUGH: + if (buffer[i+1] == OPTFALSE) + opts->no_fallthrough = NASTFALSE; + else + opts->no_fallthrough = NASTTRUE; + break; + default: + nast_set_error(s, thread_id(), NAST_UNKNOWN_OPT); + return -1; + } + } + + return 0; +} + +int +nast_options_set(nasth *s, nast_options *opts) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't set options: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c", + NASTCMD, NASTOPTSET); + bufflen += 2*sizeof(char); + + buffer[bufflen] = OPTQCACHE; + if (opts->use_qcache) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTLOCALDB; + if (opts->use_localdb) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTFALLASYNC; + if (opts->fallthrough_async) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTALWAYSFALL; + if (opts->always_fallthrough) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTFAILONCE; + if (opts->fail_once) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTNOFALLTHROUGH; + if (opts->no_fallthrough) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +int +nast_add(nasth *s, const char *query) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't add: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c%s", + NASTCMD, NASTADD, query); + bufflen += (2 + strlen(query))*sizeof(char); + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +int +nast_del(nasth *s, const char *query) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't delete: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c%s", + NASTCMD, NASTDEL, query); + bufflen += (2 + strlen(query))*sizeof(char); + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +int +nast_get(nasth *s, const char *query) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't get: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c%s", + NASTCMD, NASTGET, query); + bufflen += (2 + strlen(query))*sizeof(char); + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +void +nast_die(nasth *s) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't kill nast: no sphincter.\n"); + return; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c", + NASTCMD, NASTDIE); + bufflen += 2 * sizeof(char); + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return; +} + +int +nast_upd(nasth *s, const char *key, nast_array *valarray) +{ + char buffer[512]; + int i; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't update: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c%s%c", + NASTCMD, NASTUPD, key, NASTSEP); + bufflen += (3 + strlen(key))*sizeof(char); + + for (i = 0; i < valarray->nitems; i++) { + char *str; + short slen; + + str = valarray->items[i]->strdata; + slen = valarray->items[i]->strlen; + if (bufflen + slen > sizeof(buffer)) { + nast_set_error(s, thread_id(), NAST_NOMEM); + return -1; + } + + memcpy(buffer+bufflen, str, slen); + bufflen += slen; + + if (i < valarray->nitems - 1) { + buffer[bufflen] = NASTSEP; + bufflen += sizeof(char); + } + } + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +int +nast_stats(nasth *s) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't get stats: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c", + NASTCMD, NASTSTATS); + bufflen += 2 * sizeof(char); + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +errcodes +nast_geterr(nasth *s) +{ + nast_response *ar; + + if (s == NULL) + return NAST_SERVER_GONE; + + ar = getmyresponse(s, thread_id()); + if (ar == NULL) + return NAST_OK; + + return ar->errcode; +} + +char * +nast_errmsg(nasth *s) +{ + nast_response *ar; + errcodes ec; + + ec = nast_geterr(s); + if (ec == NAST_SERVER_ERR) { + nast_array *aa; + + ar = getmyresponse(s, thread_id()); + if (ar == NULL) + return nast_errmsgs[NAST_UNKNOWN_RESPONSE]; + + aa = build_result(s, ar->buffer, ar->bufflen); + if (aa == NULL || aa->nitems == 0) + return nast_errmsgs[NAST_UNKNOWN_RESPONSE]; + + if (ar->errmsg != NULL) + free(ar->errmsg); + + ar->errmsg = malloc(aa->items[0]->strlen); + if (ar->errmsg == NULL) + return nast_errmsgs[NAST_UNKNOWN_RESPONSE]; + + memcpy(ar->errmsg, aa->items[0]->strdata, aa->items[0]->strlen); + nast_free_result(aa); + + return ar->errmsg; + } + + return nast_errmsgs[ec]; +} diff --git a/client/.svn/text-base/thread.c.svn-base b/client/.svn/text-base/thread.c.svn-base new file mode 100644 index 0000000..bdd613a --- /dev/null +++ b/client/.svn/text-base/thread.c.svn-base @@ -0,0 +1,75 @@ +#include "conf.h" +#include "thread.h" + +#include <unistd.h> + +#ifdef THREADSAFECLIENT +#include <pthread.h> +#endif + +RCSID("$Id: thread.c,v 1.6 2000/09/13 20:21:30 shmit Exp $"); + +#ifdef THREADSAFECLIENT +short +thread_id() +{ + short i; + + i = (pthread_self() & 0xff) | (getpid() << 8); + return i; +} + +int +_nast_mutex_new(_nast_mutex_t *lock) +{ + return pthread_mutex_init(lock, NULL); +} + +void +_nast_mutex_delete(_nast_mutex_t *lock) +{ + (void)pthread_mutex_destroy(lock); +} + +int +_nast_mutex_lock(_nast_mutex_t *lock) +{ + return pthread_mutex_lock(lock); +} + +int +_nast_mutex_unlock(_nast_mutex_t *lock) +{ + return pthread_mutex_unlock(lock); +} +#else /* THREADSAFECLIENT */ +short +thread_id() +{ + return getpid(); +} + +int +_nast_mutex_new(_nast_mutex_t *lock) +{ + return 0; +} + +void +_nast_mutex_delete(_nast_mutex_t *lock) +{ + return; +} + +int +_nast_mutex_lock(_nast_mutex_t *lock) +{ + return 0; +} + +int +_nast_mutex_unlock(_nast_mutex_t *lock) +{ + return 0; +} +#endif /* THREADSAFECLIENT */ diff --git a/client/.svn/text-base/thread.h.svn-base b/client/.svn/text-base/thread.h.svn-base new file mode 100644 index 0000000..171fde1 --- /dev/null +++ b/client/.svn/text-base/thread.h.svn-base @@ -0,0 +1,19 @@ +/* $Id: thread.h,v 1.5 2000/09/13 20:21:30 shmit Exp $ */ + +#ifndef THREAD_H +# define THREAD_H + +#ifdef THREADSAFECLIENT +#include <pthread.h> + +typedef pthread_mutex_t _nast_mutex_t; +#else +typedef int _nast_mutex_t; +#endif + +short thread_id(); +int _nast_mutex_new(_nast_mutex_t *lock); +void _nast_mutex_delete(_nast_mutex_t *lock); +int _nast_mutex_lock(_nast_mutex_t *lock); +int _nast_mutex_unlock(_nast_mutex_t *lock); +#endif diff --git a/client/Makefile b/client/Makefile new file mode 100644 index 0000000..e92feed --- /dev/null +++ b/client/Makefile @@ -0,0 +1,26 @@ +# $Id: Makefile,v 1.10 2001/01/19 02:54:37 shmit Exp $ + +LIBOBJS= nastapi.o thread.o + +all-lib: + @rm -f *.o + @make "THREADFLAGS=-UTHREADSAFECLIENT" libnast.a + @rm -f *.o + @make "THREADFLAGS=-DTHREADSAFECLIENT" libnast_r.a + +libnast.a: ${LIBOBJS} + ar r $@ ${LIBOBJS} + ranlib $@ + +libnast_r.a: ${LIBOBJS} + ar r $@ ${LIBOBJS} + ranlib $@ + +# +# Dependencies +# +nastapi.o: ../include/nastd.h ../include/nastipc.h thread.h +thread.o: thread.h + +MKDIR= ../Makefiles +include ${MKDIR}/build diff --git a/client/nastapi.c b/client/nastapi.c new file mode 100644 index 0000000..3e5a3b9 --- /dev/null +++ b/client/nastapi.c @@ -0,0 +1,885 @@ +#include "conf.h" +#include "nastd.h" +#include "nastipc.h" +#include "thread.h" + +#include <errno.h> +#include <thread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <sys/un.h> +#include <signal.h> +#include <unistd.h> + +RCSID("$Id: nastapi.c,v 1.13 2001/10/29 11:17:11 shmit Exp $"); + +char *nast_errmsgs[] = { + "No errors", + "The NASTD server has gone away", + "Couldn't allocate enough memory", + "Server response is unknown", + "Connection to server timed out", + "Unknown option returned", + NULL +}; + +static nast_string_t * +nast_string_new(int slen, const char *data) +{ + nast_string_t *tmp; + + tmp = malloc(sizeof(nast_string_t)); + if (tmp == NULL) + return NULL; + + tmp->strdata = malloc((slen+1) * sizeof(char *)); + if (tmp == NULL) + return NULL; + memcpy(tmp->strdata, data, slen); + tmp->strdata[slen] = '\0'; + tmp->strlen = slen; + + return tmp; +} + +static void +nast_string_delete(nast_string_t *string) +{ + string->strlen = 0; + free(string->strdata); + string->strdata = NULL; + free(string); +} + +nast_array * +nast_array_new() +{ + nast_array *aa; + + aa = malloc(sizeof(nast_array)); + if (aa == NULL) + return NULL; + + aa->nitems = 0; + aa->items = NULL; + return aa; +} + +int +nast_array_add(nast_array *array, short len, const char *data) +{ + const int GRANULARITY = 10; + + if (array->nitems % GRANULARITY == 0) { + nast_string_t **tmp; + tmp = realloc(array->items, sizeof(char *) * + (GRANULARITY + array->nitems)); + if (tmp == NULL) + return -1; + array->items = tmp; + } + array->nitems++; + + array->items[array->nitems-1] = nast_string_new(len, data); + if (array->items[array->nitems-1] == NULL) + return -1; + + return 0; +} + +void +nast_array_delete(nast_array *array) +{ + nast_free_result(array); +} + +static nast_response * +response_new() +{ + nast_response *tmp; + + tmp = malloc(sizeof(nast_response)); + if (tmp == NULL) + return NULL; + + tmp->buffer = NULL; + tmp->bufflen = 0; + tmp->errcode = NAST_OK; + tmp->errmsg = NULL; + tmp->reqid = -1; + + return tmp; +} + +static nast_response * +getmyresponse(nasth *s, unsigned short reqid) +{ + if (s->nthreads < reqid) + return NULL; + + return s->responses[reqid-1]; +} + +static void +nast_set_error(nasth *s, unsigned short reqid, errcodes code) +{ + nast_response *ar; + + ar = getmyresponse(s, reqid); + if (ar == NULL) + return; + + ar->errcode = code; +} + +static int +grow_responses(nasth *s, unsigned short maxitems) +{ + nast_response **tmp_resp; + int i; + + if (s->nthreads >= maxitems) + return 0; + + tmp_resp = realloc(s->responses, maxitems * sizeof(nast_response *)); + if (tmp_resp == NULL) + return -1; + + s->responses = tmp_resp; + for (i = s->nthreads; i < maxitems; i++) { + s->responses[i] = response_new(); + if (s->responses[i] == NULL) + return -1; + } + + s->nthreads = maxitems; + return 0; +} + +static nast_array * +build_result(nasth *s, const char *buff, short bufflen) +{ + nast_array *aa; + const char *s_p, *e_p; + short l; + + aa = nast_array_new(); + if (aa == NULL) { + nast_set_error(s, thread_id(), NAST_NOMEM); + return NULL; + } + + /* Parse the buff into an array. */ + l = 0; + aa->nitems = 0; + aa->items = NULL; + s_p = buff+l; + for (e_p = s_p; e_p <= buff+bufflen; e_p++) { + if (e_p == buff+bufflen || *e_p == NASTSEP) { + if (nast_array_add(aa, e_p - s_p, s_p) == -1) { + nast_set_error(s, thread_id(), NAST_NOMEM); + return NULL; + } + s_p = e_p + 1; + } + } + + return aa; +} + +static int +addresponse(nasth *s, unsigned short reqid, char *buffer, short len) +{ + nast_response *ar; + + switch (buffer[0]) { + case NASTOK: + nast_set_error(s, reqid, NAST_OK); + break; + case NASTERR: + nast_set_error(s, reqid, NAST_SERVER_ERR); + break; + default: + nast_set_error(s, reqid, NAST_UNKNOWN_RESPONSE); + } + + ar = getmyresponse(s, reqid); + if (ar == NULL) { + /* + * Somehow we got a response for something we didn't + * request. + */ + return -1; + } + + ar->reqid = reqid; + ar->buffer = malloc(len-1); + if (ar->buffer == NULL) { + nast_set_error(s, reqid, NAST_NOMEM); + return -1; + } + memcpy(ar->buffer, buffer+1, len-1); + ar->bufflen = len-1; + return 0; +} + +static void +delresponse(nasth *s, unsigned short reqid) +{ + nast_response *ar; + + ar = getmyresponse(s, reqid); + if (ar == NULL) + return; + + ar->reqid = -1; + if (ar->buffer) + free(ar->buffer); + ar->bufflen = 0; +} + +static int +checkresponse(nasth *s, unsigned short reqid) +{ + nast_response *ar; + + if (reqid > s->nthreads) + return -1; + + ar = getmyresponse(s, reqid); + if (ar == NULL || (short)ar->reqid == -1) + return -1; + + return 0; +} + +static int +sendcmd(nasth *s, const char *buff, short len) +{ + ssize_t wrote; + + /* Make sure there's room in the response array. */ + if (grow_responses(s, thread_id()) == -1) { + /* + * XXX: This is a fatal error. + * Find some better way to handle this. + */ + exit(1); + } + + /* If we're sending a command, make sure we get rid of old data. */ + delresponse(s, thread_id()); + + /* Send the command. */ + wrote = 0; + while (wrote < len) { + ssize_t rc; + + rc = write(s->socket, buff + wrote, len - wrote); + if (rc == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + nast_set_error(s, thread_id(), NAST_SERVER_GONE); + return -1; + } + wrote += rc; + } + + /* Check status. */ + return 0; +} + +static int +getresponse(nasth *s) +{ + char buffer[1024]; + nast_response *ar; + int ntries, rc; + unsigned short tid; + short nbytes; + + ntries = 0; + tid = thread_id(); +reread: + _nast_mutex_lock(s->lock); + + /* + * See if we already have the response from another thread which + * may have found it first. + */ + rc = checkresponse(s, tid); + if (rc == 0) { + _nast_mutex_unlock(s->lock); + } else { + /* Not in the already read stuff, check the network. */ + char *p; + short bufflen; + unsigned short reqid; + fd_set readfds; + struct timeval timeout; + + FD_ZERO(&readfds); + FD_SET(s->socket, &readfds); + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + switch(select(s->socket+1, &readfds, NULL, NULL, &timeout)) { + case -1: + _nast_mutex_unlock(s->lock); + nast_set_error(s, tid, NAST_SERVER_GONE); + return -1; + case 0: + /* Timeout expired. */ + _nast_mutex_unlock(s->lock); + if (ntries++ < 50) + goto reread; + nast_set_error(s, tid, NAST_TIMEDOUT); + return -1; + } + nbytes = recv(s->socket, buffer, sizeof(buffer), 0); + if (nbytes == -1) { + _nast_mutex_unlock(s->lock); + nast_set_error(s, tid, NAST_SERVER_GONE); + return -1; + } else if (nbytes == 0) { + /* No response from server. That's bad. Terminate. */ + _nast_mutex_unlock(s->lock); + nast_set_error(s, tid, NAST_SERVER_GONE); + return -1; + } else if (nbytes < + sizeof(bufflen) + sizeof(reqid) + sizeof(char)) { + /* Response is too short. */ + _nast_mutex_unlock(s->lock); + nast_set_error(s, tid, NAST_UNKNOWN_RESPONSE); + return -1; + } + + for (p = buffer; p < buffer+nbytes; p += bufflen) { + int l; + + memcpy(&bufflen, p, sizeof(bufflen)); + bufflen = ntohs(bufflen); + l = sizeof(bufflen); + + /* Sanity check, just in case data gets munged. */ + if (bufflen <= 0 || bufflen > nbytes) { + _nast_mutex_unlock(s->lock); + nast_set_error(s, tid, NAST_UNKNOWN_RESPONSE); + return -1; + } + + memcpy(&reqid, p+l, sizeof(reqid)); + reqid = ntohs(reqid); + l += sizeof(reqid); + + /* Save this response on the response array. */ + addresponse(s, reqid, p+l, bufflen-l); + } + /* Check the response array to see if we got our response. */ + _nast_mutex_unlock(s->lock); + goto reread; + } + + ar = getmyresponse(s, tid); + if (ar->errcode == NAST_OK) + return 0; + else + return -1; +} + +nasth * +nast_sphincter_new(const char *sock_path) +{ + nasth *tmp_h; + struct sockaddr_un sunix; + int rc; + + tmp_h = malloc(sizeof(nasth)); + if (tmp_h == NULL) { + fprintf(stderr, + "ERROR: Couldn't make space for sphincter: %s.\n", + strerror(errno)); + return NULL; + } + + tmp_h->nthreads = 0; + tmp_h->responses = NULL; + + tmp_h->lock = malloc(sizeof(_nast_mutex_t)); + if (tmp_h->lock == NULL) { + fprintf(stderr, + "ERROR: Couldn't create NAST lock: %s.\n", + strerror(errno)); + nast_sphincter_close(tmp_h); + return NULL; + } + rc = _nast_mutex_new(tmp_h->lock); + if (rc) { + fprintf(stderr, + "ERROR: Couldn't initialise NAST lock: %s.\n", + strerror(rc)); + nast_sphincter_close(tmp_h); + return NULL; + } + + tmp_h->socket = socket(AF_UNIX, SOCK_STREAM, 0); + if (tmp_h->socket == -1) { + fprintf(stderr, + "ERROR: Couldn't initialise socket: %s.\n", + strerror(errno)); + nast_sphincter_close(tmp_h); + return NULL; + } + + memset(&sunix, 0, sizeof(sunix)); + if (sock_path == NULL) + snprintf(sunix.sun_path, sizeof(sunix.sun_path), NASTHOLE); + else + strncpy(sunix.sun_path, sock_path, sizeof(sunix.sun_path)); + sunix.sun_family = AF_UNIX; + + if (connect(tmp_h->socket, (struct sockaddr *)&sunix, + sizeof(sunix)) == -1) { + fprintf(stderr, + "ERROR: Couldn't connect to server: %s.\n", + strerror(errno)); + nast_sphincter_close(tmp_h); + return NULL; + } + return tmp_h; +} + +void +nast_sphincter_close(nasth *s) +{ + int i; + + if (s == NULL) + return; + + s->nthreads = 0; + + if (s->lock != NULL) { + _nast_mutex_delete(s->lock); + free(s->lock); + s->lock = NULL; + } + + if (s->socket != -1) { + close(s->socket); + s->socket = -1; + } + + if (s->responses != NULL) { + for (i = 0; i < s->nthreads; i++) { + if (s->responses[i]->buffer != NULL) + free(s->responses[i]->buffer); + free(s->responses[i]); + s->responses[i] = NULL; + } + free(s->responses); + s->responses = NULL; + } + + free(s); +} + +nast_array * +nast_get_result(nasth *s) +{ + nast_response *ar; + + ar = getmyresponse(s, thread_id()); + if (ar == NULL) + return NULL; + + return build_result(s, ar->buffer, ar->bufflen); +} + +void +nast_free_result(nast_array *aa) +{ + int i; + + if (aa->items) { + for (i = 0; i < aa->nitems; i++) + nast_string_delete(aa->items[i]); + free(aa->items); + aa->items = NULL; + } + aa->nitems = 0; + free(aa); +} + +static int +add_reqid(char *buffer) +{ + unsigned short tid; + + tid = thread_id(); + memcpy(buffer, &htons(tid), sizeof(tid)); + + return sizeof(tid); +} + +int +nast_options_get(nasth *s, nast_options *opts) +{ + nast_array *aa; + char buffer[512]; + short bufflen, i; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't get options: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c", + NASTCMD, NASTOPTGET); + bufflen += 2 * sizeof(char); + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + if (getresponse(s) == -1) + return -1; + + /* Copy out results and free them. */ + aa = nast_get_result(s); + + if (aa->nitems != 1) { + nast_set_error(s, thread_id(), NAST_UNKNOWN_RESPONSE); + return -1; + } + + if (sizeof(buffer) < aa->items[0]->strlen) + bufflen = sizeof(buffer); + else + bufflen = aa->items[0]->strlen; + memcpy(buffer, aa->items[0]->strdata, bufflen); + nast_free_result(aa); + + /* Parse return into options. */ + for (i = 0; i < bufflen; i+=2) { + switch (buffer[i]) { + case OPTQCACHE: + if (buffer[i+1] == OPTFALSE) + opts->use_qcache = NASTFALSE; + else + opts->use_qcache = NASTTRUE; + break; + case OPTLOCALDB: + if (buffer[i+1] == OPTFALSE) + opts->use_localdb = NASTFALSE; + else + opts->use_localdb = NASTTRUE; + break; + case OPTFALLASYNC: + if (buffer[i+1] == OPTFALSE) + opts->fallthrough_async = NASTFALSE; + else + opts->fallthrough_async = NASTTRUE; + break; + case OPTALWAYSFALL: + if (buffer[i+1] == OPTFALSE) + opts->always_fallthrough = NASTFALSE; + else + opts->always_fallthrough = NASTTRUE; + break; + case OPTFAILONCE: + if (buffer[i+1] == OPTFALSE) + opts->fail_once = NASTFALSE; + else + opts->fail_once = NASTTRUE; + break; + case OPTNOFALLTHROUGH: + if (buffer[i+1] == OPTFALSE) + opts->no_fallthrough = NASTFALSE; + else + opts->no_fallthrough = NASTTRUE; + break; + default: + nast_set_error(s, thread_id(), NAST_UNKNOWN_OPT); + return -1; + } + } + + return 0; +} + +int +nast_options_set(nasth *s, nast_options *opts) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't set options: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c", + NASTCMD, NASTOPTSET); + bufflen += 2*sizeof(char); + + buffer[bufflen] = OPTQCACHE; + if (opts->use_qcache) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTLOCALDB; + if (opts->use_localdb) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTFALLASYNC; + if (opts->fallthrough_async) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTALWAYSFALL; + if (opts->always_fallthrough) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTFAILONCE; + if (opts->fail_once) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTNOFALLTHROUGH; + if (opts->no_fallthrough) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +int +nast_add(nasth *s, const char *query) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't add: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c%s", + NASTCMD, NASTADD, query); + bufflen += (2 + strlen(query))*sizeof(char); + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +int +nast_del(nasth *s, const char *query) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't delete: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c%s", + NASTCMD, NASTDEL, query); + bufflen += (2 + strlen(query))*sizeof(char); + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +int +nast_get(nasth *s, const char *query) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't get: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c%s", + NASTCMD, NASTGET, query); + bufflen += (2 + strlen(query))*sizeof(char); + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +void +nast_die(nasth *s) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't kill nast: no sphincter.\n"); + return; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c", + NASTCMD, NASTDIE); + bufflen += 2 * sizeof(char); + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return; +} + +int +nast_upd(nasth *s, const char *key, nast_array *valarray) +{ + char buffer[512]; + int i; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't update: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c%s%c", + NASTCMD, NASTUPD, key, NASTSEP); + bufflen += (3 + strlen(key))*sizeof(char); + + for (i = 0; i < valarray->nitems; i++) { + char *str; + short slen; + + str = valarray->items[i]->strdata; + slen = valarray->items[i]->strlen; + if (bufflen + slen > sizeof(buffer)) { + nast_set_error(s, thread_id(), NAST_NOMEM); + return -1; + } + + memcpy(buffer+bufflen, str, slen); + bufflen += slen; + + if (i < valarray->nitems - 1) { + buffer[bufflen] = NASTSEP; + bufflen += sizeof(char); + } + } + + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +int +nast_stats(nasth *s) +{ + char buffer[512]; + short bufflen; + + if (s == NULL) { + fprintf(stderr, "ERROR: Can't get stats: no sphincter.\n"); + return -1; + } + + bufflen = sizeof(short); + bufflen += add_reqid(buffer+bufflen); + + snprintf(buffer+bufflen, sizeof(buffer)-bufflen, "%c%c", + NASTCMD, NASTSTATS); + bufflen += 2 * sizeof(char); + memcpy(buffer, &htons(bufflen), sizeof(short)); + sendcmd(s, buffer, bufflen); + return getresponse(s); +} + +errcodes +nast_geterr(nasth *s) +{ + nast_response *ar; + + if (s == NULL) + return NAST_SERVER_GONE; + + ar = getmyresponse(s, thread_id()); + if (ar == NULL) + return NAST_OK; + + return ar->errcode; +} + +char * +nast_errmsg(nasth *s) +{ + nast_response *ar; + errcodes ec; + + ec = nast_geterr(s); + if (ec == NAST_SERVER_ERR) { + nast_array *aa; + + ar = getmyresponse(s, thread_id()); + if (ar == NULL) + return nast_errmsgs[NAST_UNKNOWN_RESPONSE]; + + aa = build_result(s, ar->buffer, ar->bufflen); + if (aa == NULL || aa->nitems == 0) + return nast_errmsgs[NAST_UNKNOWN_RESPONSE]; + + if (ar->errmsg != NULL) + free(ar->errmsg); + + ar->errmsg = malloc(aa->items[0]->strlen); + if (ar->errmsg == NULL) + return nast_errmsgs[NAST_UNKNOWN_RESPONSE]; + + memcpy(ar->errmsg, aa->items[0]->strdata, aa->items[0]->strlen); + nast_free_result(aa); + + return ar->errmsg; + } + + return nast_errmsgs[ec]; +} diff --git a/client/thread.c b/client/thread.c new file mode 100644 index 0000000..bdd613a --- /dev/null +++ b/client/thread.c @@ -0,0 +1,75 @@ +#include "conf.h" +#include "thread.h" + +#include <unistd.h> + +#ifdef THREADSAFECLIENT +#include <pthread.h> +#endif + +RCSID("$Id: thread.c,v 1.6 2000/09/13 20:21:30 shmit Exp $"); + +#ifdef THREADSAFECLIENT +short +thread_id() +{ + short i; + + i = (pthread_self() & 0xff) | (getpid() << 8); + return i; +} + +int +_nast_mutex_new(_nast_mutex_t *lock) +{ + return pthread_mutex_init(lock, NULL); +} + +void +_nast_mutex_delete(_nast_mutex_t *lock) +{ + (void)pthread_mutex_destroy(lock); +} + +int +_nast_mutex_lock(_nast_mutex_t *lock) +{ + return pthread_mutex_lock(lock); +} + +int +_nast_mutex_unlock(_nast_mutex_t *lock) +{ + return pthread_mutex_unlock(lock); +} +#else /* THREADSAFECLIENT */ +short +thread_id() +{ + return getpid(); +} + +int +_nast_mutex_new(_nast_mutex_t *lock) +{ + return 0; +} + +void +_nast_mutex_delete(_nast_mutex_t *lock) +{ + return; +} + +int +_nast_mutex_lock(_nast_mutex_t *lock) +{ + return 0; +} + +int +_nast_mutex_unlock(_nast_mutex_t *lock) +{ + return 0; +} +#endif /* THREADSAFECLIENT */ diff --git a/client/thread.h b/client/thread.h new file mode 100644 index 0000000..171fde1 --- /dev/null +++ b/client/thread.h @@ -0,0 +1,19 @@ +/* $Id: thread.h,v 1.5 2000/09/13 20:21:30 shmit Exp $ */ + +#ifndef THREAD_H +# define THREAD_H + +#ifdef THREADSAFECLIENT +#include <pthread.h> + +typedef pthread_mutex_t _nast_mutex_t; +#else +typedef int _nast_mutex_t; +#endif + +short thread_id(); +int _nast_mutex_new(_nast_mutex_t *lock); +void _nast_mutex_delete(_nast_mutex_t *lock); +int _nast_mutex_lock(_nast_mutex_t *lock); +int _nast_mutex_unlock(_nast_mutex_t *lock); +#endif diff --git a/common/.svn/README.txt b/common/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/common/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/common/.svn/empty-file b/common/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/common/.svn/empty-file diff --git a/common/.svn/entries b/common/.svn/entries new file mode 100644 index 0000000..d8490a1 --- /dev/null +++ b/common/.svn/entries @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk/common" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + committed-rev="1" + name="compat.c" + text-time="2005-12-24T00:00:56.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="229d808e075edbd1186d8df7524b95fe" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:55.000000Z"/> +<entry + committed-rev="1" + name="Makefile" + text-time="2005-12-24T00:00:56.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="e95eae061b08a561adf70baea6075d1d" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:56.000000Z"/> +</wc-entries> diff --git a/common/.svn/format b/common/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/common/.svn/format @@ -0,0 +1 @@ +4 diff --git a/common/.svn/prop-base/Makefile.svn-base b/common/.svn/prop-base/Makefile.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/common/.svn/prop-base/Makefile.svn-base @@ -0,0 +1 @@ +END diff --git a/common/.svn/prop-base/compat.c.svn-base b/common/.svn/prop-base/compat.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/common/.svn/prop-base/compat.c.svn-base @@ -0,0 +1 @@ +END diff --git a/common/.svn/props/Makefile.svn-work b/common/.svn/props/Makefile.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/common/.svn/props/Makefile.svn-work @@ -0,0 +1 @@ +END diff --git a/common/.svn/props/compat.c.svn-work b/common/.svn/props/compat.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/common/.svn/props/compat.c.svn-work @@ -0,0 +1 @@ +END diff --git a/common/.svn/text-base/Makefile.svn-base b/common/.svn/text-base/Makefile.svn-base new file mode 100644 index 0000000..48ab187 --- /dev/null +++ b/common/.svn/text-base/Makefile.svn-base @@ -0,0 +1,9 @@ +# $Id: Makefile,v 1.2 2000/03/07 22:55:43 shmit Exp $ + +LIBOBJS= compat.o +libcompat.a: ${LIBOBJS} + ar r $@ ${LIBOBJS} + ranlib $@ + +MKDIR= ../Makefiles +include ${MKDIR}/build diff --git a/common/.svn/text-base/compat.c.svn-base b/common/.svn/text-base/compat.c.svn-base new file mode 100644 index 0000000..98fb1a1 --- /dev/null +++ b/common/.svn/text-base/compat.c.svn-base @@ -0,0 +1,55 @@ +#include "compat.h" + +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> + +RCSID("$Id: compat.c,v 1.1 2000/03/07 22:39:27 shmit Exp $"); + +#if NEED_SETPROCTITLE +void +setproctitle(const char *fmt, ...) +{ +} +#endif + +#if NEED_SNPRINTF +int +snprintf(char *str, size_t size, const char *fmt, ...) +{ + va_list ap; + int rc; + + va_start(ap, fmt); + rc = vsprintf(str, fmt, ap); + va_end(ap); + + return rc; +} +#endif + +#if NEED_MEMCPY +void * +memcpy(void *dst, const void *src, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + (char *)dst+i = (char *)src+i; + + return dst; +} +#endif + +#if NEED_MEMSET +void * +memset(void *dst, char c, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + (char *)dst+i = (char *)src+i; + + return dst; +} +#endif diff --git a/common/Makefile b/common/Makefile new file mode 100644 index 0000000..48ab187 --- /dev/null +++ b/common/Makefile @@ -0,0 +1,9 @@ +# $Id: Makefile,v 1.2 2000/03/07 22:55:43 shmit Exp $ + +LIBOBJS= compat.o +libcompat.a: ${LIBOBJS} + ar r $@ ${LIBOBJS} + ranlib $@ + +MKDIR= ../Makefiles +include ${MKDIR}/build diff --git a/common/compat.c b/common/compat.c new file mode 100644 index 0000000..98fb1a1 --- /dev/null +++ b/common/compat.c @@ -0,0 +1,55 @@ +#include "compat.h" + +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> + +RCSID("$Id: compat.c,v 1.1 2000/03/07 22:39:27 shmit Exp $"); + +#if NEED_SETPROCTITLE +void +setproctitle(const char *fmt, ...) +{ +} +#endif + +#if NEED_SNPRINTF +int +snprintf(char *str, size_t size, const char *fmt, ...) +{ + va_list ap; + int rc; + + va_start(ap, fmt); + rc = vsprintf(str, fmt, ap); + va_end(ap); + + return rc; +} +#endif + +#if NEED_MEMCPY +void * +memcpy(void *dst, const void *src, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + (char *)dst+i = (char *)src+i; + + return dst; +} +#endif + +#if NEED_MEMSET +void * +memset(void *dst, char c, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + (char *)dst+i = (char *)src+i; + + return dst; +} +#endif diff --git a/include/.svn/README.txt b/include/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/include/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/include/.svn/empty-file b/include/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/include/.svn/empty-file diff --git a/include/.svn/entries b/include/.svn/entries new file mode 100644 index 0000000..e9a15b6 --- /dev/null +++ b/include/.svn/entries @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk/include" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + committed-rev="1" + name="nastd.h" + text-time="2005-12-24T00:00:48.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="a2a8507454598351d2fb4d92de8fac34" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:47.000000Z"/> +<entry + committed-rev="1" + name="nastipc.h" + text-time="2005-12-24T00:00:48.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="c9c5a4de31ca1526065fba75540ca47d" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:48.000000Z"/> +<entry + committed-rev="1" + name="compat.h" + text-time="2005-12-24T00:00:48.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="59e26d4dfdabe5879df3b1d38bc20380" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:48.000000Z"/> +<entry + committed-rev="1" + name="conf.h" + text-time="2005-12-24T00:00:48.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="687df4cd84fcc53ab4edb6cb1bc967e0" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:48.000000Z"/> +<entry + committed-rev="1" + name="config.h" + text-time="2005-12-24T00:00:48.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="6ff11b17126158149127110856fcab5d" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:48.000000Z"/> +<entry + committed-rev="1" + name="version.h" + text-time="2005-12-24T00:00:48.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="c8e8460535f050ccc9e1a8024b65afde" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:48.000000Z"/> +</wc-entries> diff --git a/include/.svn/format b/include/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/include/.svn/format @@ -0,0 +1 @@ +4 diff --git a/include/.svn/prop-base/compat.h.svn-base b/include/.svn/prop-base/compat.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/prop-base/compat.h.svn-base @@ -0,0 +1 @@ +END diff --git a/include/.svn/prop-base/conf.h.svn-base b/include/.svn/prop-base/conf.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/prop-base/conf.h.svn-base @@ -0,0 +1 @@ +END diff --git a/include/.svn/prop-base/config.h.svn-base b/include/.svn/prop-base/config.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/prop-base/config.h.svn-base @@ -0,0 +1 @@ +END diff --git a/include/.svn/prop-base/nastd.h.svn-base b/include/.svn/prop-base/nastd.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/prop-base/nastd.h.svn-base @@ -0,0 +1 @@ +END diff --git a/include/.svn/prop-base/nastipc.h.svn-base b/include/.svn/prop-base/nastipc.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/prop-base/nastipc.h.svn-base @@ -0,0 +1 @@ +END diff --git a/include/.svn/prop-base/version.h.svn-base b/include/.svn/prop-base/version.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/prop-base/version.h.svn-base @@ -0,0 +1 @@ +END diff --git a/include/.svn/props/compat.h.svn-work b/include/.svn/props/compat.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/props/compat.h.svn-work @@ -0,0 +1 @@ +END diff --git a/include/.svn/props/conf.h.svn-work b/include/.svn/props/conf.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/props/conf.h.svn-work @@ -0,0 +1 @@ +END diff --git a/include/.svn/props/config.h.svn-work b/include/.svn/props/config.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/props/config.h.svn-work @@ -0,0 +1 @@ +END diff --git a/include/.svn/props/nastd.h.svn-work b/include/.svn/props/nastd.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/props/nastd.h.svn-work @@ -0,0 +1 @@ +END diff --git a/include/.svn/props/nastipc.h.svn-work b/include/.svn/props/nastipc.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/props/nastipc.h.svn-work @@ -0,0 +1 @@ +END diff --git a/include/.svn/props/version.h.svn-work b/include/.svn/props/version.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/include/.svn/props/version.h.svn-work @@ -0,0 +1 @@ +END diff --git a/include/.svn/text-base/compat.h.svn-base b/include/.svn/text-base/compat.h.svn-base new file mode 100644 index 0000000..3d1e3e6 --- /dev/null +++ b/include/.svn/text-base/compat.h.svn-base @@ -0,0 +1,83 @@ +/* $Id: compat.h,v 1.4 2000/03/21 19:06:58 shmit Exp $ */ + +#ifndef COMPAT_H +# define COMPAT_H + +#include <netdb.h> +#include <syslog.h> +#include <sys/param.h> +#include <sys/types.h> +#include <netinet/in.h> + +#if __GNUC__ +#define RCSID(x) static const char rcsid[] __attribute__((__unused__)) = x +#else +#define RCSID(x) static const char rcsid[] = x +#endif + +#if OS_SOLARIS +#define NEED_SNPRINTF 1 +#define NEED_SHADOW 1 +#define NEED_CRYPT 1 +#define NEED_SETPROCTITLE 1 +#define NEED_STRINGS 1 + +#if SOLARIS_55 +#define NEED_CRYPT 1 +#include <pthread.h> +#endif +#endif /* OS_SOLARIS */ + +#if OS_FREEBSD +#include <libutil.h> + +#if FREEBSD_2 +typedef u_int32_t uint32_t; +#endif /* FREEBSD_2 */ +#endif /* OS_FREEBSD */ + +#if OS_LINUX +#define NEED_SETPROCTITLE 1 +#endif /* OS_LINUX */ + +#ifndef LOG_PERROR +#define LOG_PERROR 0 +#endif + +#ifndef IPPORT_HIFIRSTAUTO +#define IPPORT_HIFIRSTAUTO 49152 +#endif + +#ifndef IPPORT_HILASTAUTO +#define IPPORT_HILASTAUTO 65535 +#endif + +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 1024 +#endif + +#if NEED_SETPROCTITLE +void setproctitle(const char *fmt, ...); +#endif + +#if NEED_SNPRINTF +int snprintf(char *str, size_t size, const char *fmt, ...); +#endif + +#if NEED_MEMCPY +void *memcpy(void *dst, const void *src, size_t len); +#endif + +#if NEED_MEMSET +void *memcpy(void *dst, char c, size_t len); +#endif + +#if NEED_SETPROCTITLE +void setproctitle(const char *fmt, ...); +#endif + +#endif diff --git a/include/.svn/text-base/conf.h.svn-base b/include/.svn/text-base/conf.h.svn-base new file mode 100644 index 0000000..1b6ed37 --- /dev/null +++ b/include/.svn/text-base/conf.h.svn-base @@ -0,0 +1,16 @@ +/* $Id: conf.h,v 1.6 2000/11/15 20:20:50 shmit Exp $ */ + +#ifndef CONF_H +#define CONF_H + +#include <compat.h> +#include <version.h> + +#define PERIODICITY 30 /* How many seconds between + periodic functions. */ + +#ifndef DATADIR +#define DATADIR "/home/shmit/libdata/nastd" +#endif + +#endif diff --git a/include/.svn/text-base/config.h.svn-base b/include/.svn/text-base/config.h.svn-base new file mode 100644 index 0000000..36d3611 --- /dev/null +++ b/include/.svn/text-base/config.h.svn-base @@ -0,0 +1,40 @@ +/* $Id: config.h,v 1.3 2001/11/09 15:54:37 shmit Exp $ */ + +#ifndef CONFIG_H +# define CONFIG_H + +enum data_type { NUMBER, STRING, ARRAY, DICTIONARY }; + +struct conf_entry { + char *name; + void *data; + int namelen, datalen; + enum data_type type; + int num_entries; +}; +typedef struct conf_entry conf_entry_t; + +struct nast_config { + char *description; + char *nast_dir; + char *nast_sock; + char *nast_cdb_file; + char *mysql_host; + char *mysql_user; + char *mysql_pass; + int nofork_flag; + int null_cache_timeout; + int tcp_port; +}; + +extern struct nast_config config; + +int config_init(); +void config_delete(); +void config_setdefaults(); +void *config_find(void *root_node, const char *name, enum data_type *type); +void *config_arrayitemat(void *array, int index, enum data_type *type); +void *config_dictitemat(void *dict, const char *name, enum data_type *type); +void *getdata(void *itemref, void *dst, enum data_type want_type); + +#endif diff --git a/include/.svn/text-base/nastd.h.svn-base b/include/.svn/text-base/nastd.h.svn-base new file mode 100644 index 0000000..b1fbaa4 --- /dev/null +++ b/include/.svn/text-base/nastd.h.svn-base @@ -0,0 +1,85 @@ +/* $Id: nastd.h,v 1.7 2001/10/29 11:17:12 shmit Exp $ */ + +#ifndef NASTD_H +#define NASTD_H + +enum _nast_bool { NASTFALSE = 0, NASTTRUE = 1 }; +typedef enum _nast_bool nast_bool; + +enum _errcodes { + NAST_OK = 0, + NAST_SERVER_GONE = 1, + NAST_NOMEM = 2, + NAST_UNKNOWN_RESPONSE = 3, + NAST_TIMEDOUT = 4, + NAST_UNKNOWN_OPT = 5, + NAST_SERVER_ERR +}; +typedef enum _errcodes errcodes; + +struct _nast_options { + nast_bool use_qcache; + nast_bool use_localdb; + nast_bool fallthrough_async; + nast_bool always_fallthrough; + nast_bool fail_once; + nast_bool no_fallthrough; +}; +typedef struct _nast_options nast_options; + +struct _nast_string_t { + char *strdata; + int strlen; +}; +typedef struct _nast_string_t nast_string_t; + +struct _nast_array { + int nitems; + nast_string_t **items; +}; +typedef struct _nast_array nast_array; + +struct _nast_response { + char *buffer; + char *errmsg; + errcodes errcode; + short bufflen; + unsigned short reqid; +}; +typedef struct _nast_response nast_response; + +struct _nast_sphincter { + nast_response **responses; + void *lock; + int socket; + int nthreads; +}; +typedef struct _nast_sphincter nasth; + +nasth *nast_sphincter_new(const char *sock_path); +int nast_sphincter_connect(nasth *sphincter, const char *hostname, + unsigned short port, const char *username, + const char *password); +void nast_sphincter_close(nasth *sphincter); + +nast_array *nast_get_result(nasth *sphincter); +void nast_free_result(nast_array *result); + +nast_array *nast_array_new(); +int nast_array_add(nast_array *array, short len, const char *data); +void nast_array_delete(nast_array *array); + +int nast_options_set(nasth *sphincter, nast_options *opts); +int nast_options_get(nasth *sphincter, nast_options *opts); + +int nast_add(nasth *sphincter, const char *query); +int nast_del(nasth *sphincter, const char *query); +int nast_get(nasth *sphincter, const char *query); +int nast_upd(nasth *sphincter, const char *key, nast_array *valarray); + +int nast_stats(nasth *sphincter); + +errcodes nast_geterr(nasth *sphincter); +char *nast_errmsg(nasth *sphincter); + +#endif diff --git a/include/.svn/text-base/nastipc.h.svn-base b/include/.svn/text-base/nastipc.h.svn-base new file mode 100644 index 0000000..7309e8b --- /dev/null +++ b/include/.svn/text-base/nastipc.h.svn-base @@ -0,0 +1,69 @@ +/* $Id: nastipc.h,v 1.3 2001/01/19 00:29:26 shmit Exp $ */ + +#ifndef NASTIPC_H +#define NASTIPC_H + +#define NASTHOLE "/tmp/nastd.sock" + +/* Protocol section */ + +/* + * Send NASTESC to start a new command. The next byte specifies the + * type of command. + */ +#define NASTCMD '\xff' + +/* + * Commands, prefixed by NASTCMD. + */ +#define NASTADD '\x01' +#define NASTDEL '\x02' +#define NASTUPD '\x03' +#define NASTGET '\x04' +#define NASTDIE '\x0f' + +/* Commands for server options. */ +#define NASTOPTGET '\x10' +#define NASTOPTSET '\x11' + +/* Command to get stats. */ +#define NASTSTATS '\x20' + +/* Server -> client responses. These can be postfixed with a string. */ +#define NASTOK '\xf1' +#define NASTERR '\xf2' +#define NASTARG '\xe0' + +/* The quote character, for globbing multiple strings together. */ +#define NASTQUOTE '\xfe' + +/* + * The escape character, to send binary that may be interpereted + * incorrectly. + */ +#define NASTESC '\xfd' + +/* Item seperator, for returning multiple items in one response. */ +#define NASTSEP '\xfc' + +/* + * The options. Ass more get added to the protocol, just add them here. + * Do not dupe option numbers. That'd be bad. + * Use these after the NASTCMD NASTOPTGET sequence. All options require + * an argument. Most are true/false, but some will require other types. + * Check nastd.h for option types. + * (e.g.: NASTCMD NASTOPTGET OPTQCACHE OPTFALSE - don't use the query cache) + * (e.g.: NASTCMD NASTOPTGET OPTNTHREADS 0x10 - allocate 16 threads) + */ +#define OPTFALSE '\x00' +#define OPTTRUE '\x01' + +#define OPTQCACHE '\x01' +#define OPTLOCALDB '\x02' +#define OPTFALLASYNC '\x03' +#define OPTALWAYSFALL '\x04' +#define OPTFAILONCE '\x05' +#define OPTNTHREADS '\x06' +#define OPTNOFALLTHROUGH '\x07' + +#endif diff --git a/include/.svn/text-base/version.h.svn-base b/include/.svn/text-base/version.h.svn-base new file mode 100644 index 0000000..efd9441 --- /dev/null +++ b/include/.svn/text-base/version.h.svn-base @@ -0,0 +1,8 @@ +/* $Id: version.h,v 1.5 2001/05/30 21:00:12 shmit Exp $ */ + +#ifndef VERSION_H +#define VERSION_H + +#define VERSION "nast 1.2.0-devel $Date: 2001/05/30 21:00:12 $" + +#endif diff --git a/include/compat.h b/include/compat.h new file mode 100644 index 0000000..3d1e3e6 --- /dev/null +++ b/include/compat.h @@ -0,0 +1,83 @@ +/* $Id: compat.h,v 1.4 2000/03/21 19:06:58 shmit Exp $ */ + +#ifndef COMPAT_H +# define COMPAT_H + +#include <netdb.h> +#include <syslog.h> +#include <sys/param.h> +#include <sys/types.h> +#include <netinet/in.h> + +#if __GNUC__ +#define RCSID(x) static const char rcsid[] __attribute__((__unused__)) = x +#else +#define RCSID(x) static const char rcsid[] = x +#endif + +#if OS_SOLARIS +#define NEED_SNPRINTF 1 +#define NEED_SHADOW 1 +#define NEED_CRYPT 1 +#define NEED_SETPROCTITLE 1 +#define NEED_STRINGS 1 + +#if SOLARIS_55 +#define NEED_CRYPT 1 +#include <pthread.h> +#endif +#endif /* OS_SOLARIS */ + +#if OS_FREEBSD +#include <libutil.h> + +#if FREEBSD_2 +typedef u_int32_t uint32_t; +#endif /* FREEBSD_2 */ +#endif /* OS_FREEBSD */ + +#if OS_LINUX +#define NEED_SETPROCTITLE 1 +#endif /* OS_LINUX */ + +#ifndef LOG_PERROR +#define LOG_PERROR 0 +#endif + +#ifndef IPPORT_HIFIRSTAUTO +#define IPPORT_HIFIRSTAUTO 49152 +#endif + +#ifndef IPPORT_HILASTAUTO +#define IPPORT_HILASTAUTO 65535 +#endif + +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 1024 +#endif + +#if NEED_SETPROCTITLE +void setproctitle(const char *fmt, ...); +#endif + +#if NEED_SNPRINTF +int snprintf(char *str, size_t size, const char *fmt, ...); +#endif + +#if NEED_MEMCPY +void *memcpy(void *dst, const void *src, size_t len); +#endif + +#if NEED_MEMSET +void *memcpy(void *dst, char c, size_t len); +#endif + +#if NEED_SETPROCTITLE +void setproctitle(const char *fmt, ...); +#endif + +#endif diff --git a/include/conf.h b/include/conf.h new file mode 100644 index 0000000..1b6ed37 --- /dev/null +++ b/include/conf.h @@ -0,0 +1,16 @@ +/* $Id: conf.h,v 1.6 2000/11/15 20:20:50 shmit Exp $ */ + +#ifndef CONF_H +#define CONF_H + +#include <compat.h> +#include <version.h> + +#define PERIODICITY 30 /* How many seconds between + periodic functions. */ + +#ifndef DATADIR +#define DATADIR "/home/shmit/libdata/nastd" +#endif + +#endif diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..36d3611 --- /dev/null +++ b/include/config.h @@ -0,0 +1,40 @@ +/* $Id: config.h,v 1.3 2001/11/09 15:54:37 shmit Exp $ */ + +#ifndef CONFIG_H +# define CONFIG_H + +enum data_type { NUMBER, STRING, ARRAY, DICTIONARY }; + +struct conf_entry { + char *name; + void *data; + int namelen, datalen; + enum data_type type; + int num_entries; +}; +typedef struct conf_entry conf_entry_t; + +struct nast_config { + char *description; + char *nast_dir; + char *nast_sock; + char *nast_cdb_file; + char *mysql_host; + char *mysql_user; + char *mysql_pass; + int nofork_flag; + int null_cache_timeout; + int tcp_port; +}; + +extern struct nast_config config; + +int config_init(); +void config_delete(); +void config_setdefaults(); +void *config_find(void *root_node, const char *name, enum data_type *type); +void *config_arrayitemat(void *array, int index, enum data_type *type); +void *config_dictitemat(void *dict, const char *name, enum data_type *type); +void *getdata(void *itemref, void *dst, enum data_type want_type); + +#endif diff --git a/include/nastd.h b/include/nastd.h new file mode 100644 index 0000000..b1fbaa4 --- /dev/null +++ b/include/nastd.h @@ -0,0 +1,85 @@ +/* $Id: nastd.h,v 1.7 2001/10/29 11:17:12 shmit Exp $ */ + +#ifndef NASTD_H +#define NASTD_H + +enum _nast_bool { NASTFALSE = 0, NASTTRUE = 1 }; +typedef enum _nast_bool nast_bool; + +enum _errcodes { + NAST_OK = 0, + NAST_SERVER_GONE = 1, + NAST_NOMEM = 2, + NAST_UNKNOWN_RESPONSE = 3, + NAST_TIMEDOUT = 4, + NAST_UNKNOWN_OPT = 5, + NAST_SERVER_ERR +}; +typedef enum _errcodes errcodes; + +struct _nast_options { + nast_bool use_qcache; + nast_bool use_localdb; + nast_bool fallthrough_async; + nast_bool always_fallthrough; + nast_bool fail_once; + nast_bool no_fallthrough; +}; +typedef struct _nast_options nast_options; + +struct _nast_string_t { + char *strdata; + int strlen; +}; +typedef struct _nast_string_t nast_string_t; + +struct _nast_array { + int nitems; + nast_string_t **items; +}; +typedef struct _nast_array nast_array; + +struct _nast_response { + char *buffer; + char *errmsg; + errcodes errcode; + short bufflen; + unsigned short reqid; +}; +typedef struct _nast_response nast_response; + +struct _nast_sphincter { + nast_response **responses; + void *lock; + int socket; + int nthreads; +}; +typedef struct _nast_sphincter nasth; + +nasth *nast_sphincter_new(const char *sock_path); +int nast_sphincter_connect(nasth *sphincter, const char *hostname, + unsigned short port, const char *username, + const char *password); +void nast_sphincter_close(nasth *sphincter); + +nast_array *nast_get_result(nasth *sphincter); +void nast_free_result(nast_array *result); + +nast_array *nast_array_new(); +int nast_array_add(nast_array *array, short len, const char *data); +void nast_array_delete(nast_array *array); + +int nast_options_set(nasth *sphincter, nast_options *opts); +int nast_options_get(nasth *sphincter, nast_options *opts); + +int nast_add(nasth *sphincter, const char *query); +int nast_del(nasth *sphincter, const char *query); +int nast_get(nasth *sphincter, const char *query); +int nast_upd(nasth *sphincter, const char *key, nast_array *valarray); + +int nast_stats(nasth *sphincter); + +errcodes nast_geterr(nasth *sphincter); +char *nast_errmsg(nasth *sphincter); + +#endif diff --git a/include/nastipc.h b/include/nastipc.h new file mode 100644 index 0000000..7309e8b --- /dev/null +++ b/include/nastipc.h @@ -0,0 +1,69 @@ +/* $Id: nastipc.h,v 1.3 2001/01/19 00:29:26 shmit Exp $ */ + +#ifndef NASTIPC_H +#define NASTIPC_H + +#define NASTHOLE "/tmp/nastd.sock" + +/* Protocol section */ + +/* + * Send NASTESC to start a new command. The next byte specifies the + * type of command. + */ +#define NASTCMD '\xff' + +/* + * Commands, prefixed by NASTCMD. + */ +#define NASTADD '\x01' +#define NASTDEL '\x02' +#define NASTUPD '\x03' +#define NASTGET '\x04' +#define NASTDIE '\x0f' + +/* Commands for server options. */ +#define NASTOPTGET '\x10' +#define NASTOPTSET '\x11' + +/* Command to get stats. */ +#define NASTSTATS '\x20' + +/* Server -> client responses. These can be postfixed with a string. */ +#define NASTOK '\xf1' +#define NASTERR '\xf2' +#define NASTARG '\xe0' + +/* The quote character, for globbing multiple strings together. */ +#define NASTQUOTE '\xfe' + +/* + * The escape character, to send binary that may be interpereted + * incorrectly. + */ +#define NASTESC '\xfd' + +/* Item seperator, for returning multiple items in one response. */ +#define NASTSEP '\xfc' + +/* + * The options. Ass more get added to the protocol, just add them here. + * Do not dupe option numbers. That'd be bad. + * Use these after the NASTCMD NASTOPTGET sequence. All options require + * an argument. Most are true/false, but some will require other types. + * Check nastd.h for option types. + * (e.g.: NASTCMD NASTOPTGET OPTQCACHE OPTFALSE - don't use the query cache) + * (e.g.: NASTCMD NASTOPTGET OPTNTHREADS 0x10 - allocate 16 threads) + */ +#define OPTFALSE '\x00' +#define OPTTRUE '\x01' + +#define OPTQCACHE '\x01' +#define OPTLOCALDB '\x02' +#define OPTFALLASYNC '\x03' +#define OPTALWAYSFALL '\x04' +#define OPTFAILONCE '\x05' +#define OPTNTHREADS '\x06' +#define OPTNOFALLTHROUGH '\x07' + +#endif diff --git a/include/version.h b/include/version.h new file mode 100644 index 0000000..efd9441 --- /dev/null +++ b/include/version.h @@ -0,0 +1,8 @@ +/* $Id: version.h,v 1.5 2001/05/30 21:00:12 shmit Exp $ */ + +#ifndef VERSION_H +#define VERSION_H + +#define VERSION "nast 1.2.0-devel $Date: 2001/05/30 21:00:12 $" + +#endif diff --git a/libconfig/.cvsignore b/libconfig/.cvsignore new file mode 100644 index 0000000..afcbfe8 --- /dev/null +++ b/libconfig/.cvsignore @@ -0,0 +1,15 @@ +radiusd +radctl +radpass +radpwtst +radacct +radterminate +radiusd.pid +radiusd.core +Makefiles/os/target +*.o +*.so +*.a +*.core +*.gmon +tags diff --git a/libconfig/.pure b/libconfig/.pure new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/libconfig/.pure diff --git a/libconfig/.svn/README.txt b/libconfig/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/libconfig/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/libconfig/.svn/empty-file b/libconfig/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/libconfig/.svn/empty-file diff --git a/libconfig/.svn/entries b/libconfig/.svn/entries new file mode 100644 index 0000000..8a68b21 --- /dev/null +++ b/libconfig/.svn/entries @@ -0,0 +1,202 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk/libconfig" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + committed-rev="1" + name="NumData.h" + text-time="2005-12-24T00:01:00.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="f0bc8bcac885c33fae6b388cbdb2993b" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:57.000000Z"/> +<entry + committed-rev="1" + name="Parser.h" + text-time="2005-12-24T00:01:00.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="7b1df589d7cf17b360f454ea5a8b8a75" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:57.000000Z"/> +<entry + committed-rev="1" + name="NumData.m" + text-time="2005-12-24T00:01:00.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="d7d513d55f5b2f49a1c2a7c3f25c607d" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:57.000000Z"/> +<entry + committed-rev="1" + name="StringData.h" + text-time="2005-12-24T00:01:00.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="b71ed77078d9ecdb0e1d35916ecd34c2" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:57.000000Z"/> +<entry + committed-rev="1" + name="Parser.m" + text-time="2005-12-24T00:01:00.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="a53cf0bea060a85d392626f2c94743ec" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:57.000000Z"/> +<entry + committed-rev="1" + name=".pure" + text-time="2005-12-24T00:01:01.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="d41d8cd98f00b204e9800998ecf8427e" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:58.000000Z"/> +<entry + committed-rev="1" + name="StringData.m" + text-time="2005-12-24T00:01:01.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="11882741e1ffc0eaffcac8be00f66260" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:58.000000Z"/> +<entry + committed-rev="1" + name="String.h" + text-time="2005-12-24T00:01:01.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="5b4aacb4740fc4011707463414825c1e" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:58.000000Z"/> +<entry + committed-rev="1" + name="ArrayData.h" + text-time="2005-12-24T00:01:01.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="36413ddac4334f96f517dbb4c345233e" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:58.000000Z"/> +<entry + committed-rev="1" + name="Data.h" + text-time="2005-12-24T00:01:01.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="03560d07811808854cd76458597260e1" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:58.000000Z"/> +<entry + committed-rev="1" + name="config.m" + text-time="2005-12-24T00:01:02.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="96c499111fc8af7aa5d577175c0e686d" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:59.000000Z"/> +<entry + committed-rev="1" + name="BuffIO.h" + text-time="2005-12-24T00:01:01.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="e965c2fafb52c388d7aca469112f1e77" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:58.000000Z"/> +<entry + committed-rev="1" + name="String.m" + text-time="2005-12-24T00:01:02.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="c1e8fe9a7cb472bb543a4ff3c08e7357" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:59.000000Z"/> +<entry + committed-rev="1" + name="ArrayData.m" + text-time="2005-12-24T00:01:02.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="6e30e0b55fa6a60befe3d7b3b11613d0" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:59.000000Z"/> +<entry + committed-rev="1" + name="DictData.h" + text-time="2005-12-24T00:01:02.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="8fea54e50780f21f4cb95ee16a402f05" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:59.000000Z"/> +<entry + committed-rev="1" + name="Data.m" + text-time="2005-12-24T00:01:02.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="d1d9d9dd062f32cdf17168e1b1be86d6" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:59.000000Z"/> +<entry + committed-rev="1" + name="BuffIO.m" + text-time="2005-12-24T00:01:02.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="e6751ba80a47e13ed8ec55e568d6d9f3" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:59.000000Z"/> +<entry + committed-rev="1" + name="DictData.m" + text-time="2005-12-24T00:01:02.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="3db081896c8282d290e88914619cdff1" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:59.000000Z"/> +<entry + committed-rev="1" + name="COPYRIGHT" + text-time="2005-12-24T00:01:02.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="f8d5134885de20571cd0b6ca9a3313d8" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:01:00.000000Z"/> +<entry + committed-rev="1" + name="Makefile" + text-time="2005-12-24T00:01:03.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="484e04bcaacde2d0cf55dc18f8a9a799" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:01:00.000000Z"/> +<entry + committed-rev="1" + name=".cvsignore" + text-time="2005-12-24T00:01:03.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="11c2ac373f2d4ba2c5a696bd87529357" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:01:00.000000Z"/> +</wc-entries> diff --git a/libconfig/.svn/format b/libconfig/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/libconfig/.svn/format @@ -0,0 +1 @@ +4 diff --git a/libconfig/.svn/prop-base/.cvsignore.svn-base b/libconfig/.svn/prop-base/.cvsignore.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/.cvsignore.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/.pure.svn-base b/libconfig/.svn/prop-base/.pure.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/.pure.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/ArrayData.h.svn-base b/libconfig/.svn/prop-base/ArrayData.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/ArrayData.h.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/ArrayData.m.svn-base b/libconfig/.svn/prop-base/ArrayData.m.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/ArrayData.m.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/BuffIO.h.svn-base b/libconfig/.svn/prop-base/BuffIO.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/BuffIO.h.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/BuffIO.m.svn-base b/libconfig/.svn/prop-base/BuffIO.m.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/BuffIO.m.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/COPYRIGHT.svn-base b/libconfig/.svn/prop-base/COPYRIGHT.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/COPYRIGHT.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/Data.h.svn-base b/libconfig/.svn/prop-base/Data.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/Data.h.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/Data.m.svn-base b/libconfig/.svn/prop-base/Data.m.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/Data.m.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/DictData.h.svn-base b/libconfig/.svn/prop-base/DictData.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/DictData.h.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/DictData.m.svn-base b/libconfig/.svn/prop-base/DictData.m.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/DictData.m.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/Makefile.svn-base b/libconfig/.svn/prop-base/Makefile.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/Makefile.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/NumData.h.svn-base b/libconfig/.svn/prop-base/NumData.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/NumData.h.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/NumData.m.svn-base b/libconfig/.svn/prop-base/NumData.m.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/NumData.m.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/Parser.h.svn-base b/libconfig/.svn/prop-base/Parser.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/Parser.h.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/Parser.m.svn-base b/libconfig/.svn/prop-base/Parser.m.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/Parser.m.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/String.h.svn-base b/libconfig/.svn/prop-base/String.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/String.h.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/String.m.svn-base b/libconfig/.svn/prop-base/String.m.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/String.m.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/StringData.h.svn-base b/libconfig/.svn/prop-base/StringData.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/StringData.h.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/StringData.m.svn-base b/libconfig/.svn/prop-base/StringData.m.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/StringData.m.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/prop-base/config.m.svn-base b/libconfig/.svn/prop-base/config.m.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/prop-base/config.m.svn-base @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/.cvsignore.svn-work b/libconfig/.svn/props/.cvsignore.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/.cvsignore.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/.pure.svn-work b/libconfig/.svn/props/.pure.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/.pure.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/ArrayData.h.svn-work b/libconfig/.svn/props/ArrayData.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/ArrayData.h.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/ArrayData.m.svn-work b/libconfig/.svn/props/ArrayData.m.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/ArrayData.m.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/BuffIO.h.svn-work b/libconfig/.svn/props/BuffIO.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/BuffIO.h.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/BuffIO.m.svn-work b/libconfig/.svn/props/BuffIO.m.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/BuffIO.m.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/COPYRIGHT.svn-work b/libconfig/.svn/props/COPYRIGHT.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/COPYRIGHT.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/Data.h.svn-work b/libconfig/.svn/props/Data.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/Data.h.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/Data.m.svn-work b/libconfig/.svn/props/Data.m.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/Data.m.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/DictData.h.svn-work b/libconfig/.svn/props/DictData.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/DictData.h.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/DictData.m.svn-work b/libconfig/.svn/props/DictData.m.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/DictData.m.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/Makefile.svn-work b/libconfig/.svn/props/Makefile.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/Makefile.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/NumData.h.svn-work b/libconfig/.svn/props/NumData.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/NumData.h.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/NumData.m.svn-work b/libconfig/.svn/props/NumData.m.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/NumData.m.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/Parser.h.svn-work b/libconfig/.svn/props/Parser.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/Parser.h.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/Parser.m.svn-work b/libconfig/.svn/props/Parser.m.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/Parser.m.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/String.h.svn-work b/libconfig/.svn/props/String.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/String.h.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/String.m.svn-work b/libconfig/.svn/props/String.m.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/String.m.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/StringData.h.svn-work b/libconfig/.svn/props/StringData.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/StringData.h.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/StringData.m.svn-work b/libconfig/.svn/props/StringData.m.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/StringData.m.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/props/config.m.svn-work b/libconfig/.svn/props/config.m.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/libconfig/.svn/props/config.m.svn-work @@ -0,0 +1 @@ +END diff --git a/libconfig/.svn/text-base/.cvsignore.svn-base b/libconfig/.svn/text-base/.cvsignore.svn-base new file mode 100644 index 0000000..afcbfe8 --- /dev/null +++ b/libconfig/.svn/text-base/.cvsignore.svn-base @@ -0,0 +1,15 @@ +radiusd +radctl +radpass +radpwtst +radacct +radterminate +radiusd.pid +radiusd.core +Makefiles/os/target +*.o +*.so +*.a +*.core +*.gmon +tags diff --git a/libconfig/.svn/text-base/.pure.svn-base b/libconfig/.svn/text-base/.pure.svn-base new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/libconfig/.svn/text-base/.pure.svn-base diff --git a/libconfig/.svn/text-base/ArrayData.h.svn-base b/libconfig/.svn/text-base/ArrayData.h.svn-base new file mode 100644 index 0000000..246803e --- /dev/null +++ b/libconfig/.svn/text-base/ArrayData.h.svn-base @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef ARRAYDATA_H +# define ARRAYDATA_H + +#include "Data.h" + +@interface ArrayData: DataObject +{ + id *data; + int numChildren; + int curObj; +} +-free; +-(int)numObjects; +-addChild: child; +-objectAt: (int)index; +@end +#endif diff --git a/libconfig/.svn/text-base/ArrayData.m.svn-base b/libconfig/.svn/text-base/ArrayData.m.svn-base new file mode 100644 index 0000000..dfee1e7 --- /dev/null +++ b/libconfig/.svn/text-base/ArrayData.m.svn-base @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "ArrayData.h" +#include "Parser.h" +#include "String.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +@implementation ArrayData +-init +{ + self = [super init]; + + numChildren = 0; + curObj = 0; + data = malloc(MALLOC_GRANULARITY * sizeof(DictEntry *)); + if (!data) { + fprintf(stderr, "ERROR: couldn't allocate memory: %s.\n", + strerror(errno)); + return nil; + } + + return self; +} + +-free +{ + int i; + + fprintf(stderr, "DEBUG: freeing array\n"); + for (i = 0; i < numChildren; i++) + [data[i] free]; + free(data); + [super free]; + + return nil; +} + +-addChild: child +{ + /* Allocate additional space for children pointers, if required. */ + if (numChildren % MALLOC_GRANULARITY == 0) { + /* TODO: fail gracefully. */ + data = realloc(data, (numChildren+MALLOC_GRANULARITY) * + sizeof(DataObject *)); + if (!data) { + fprintf(stderr, + "ERROR: couldn't allocate memory: %s.\n", + strerror(errno)); + return nil; + } + } + + data[numChildren] = child; + + numChildren++; + return self; +} + +-setFromBuffer: (const char *)buffer withLength: (int)len +{ + Parser *parser; + String *string; + const char *offset; + + self = [super init]; + parser = [Parser new]; + string = [[String new] init]; + if (parser == nil || string == nil) + return nil; + + if (buffer[len] == '\0') + len--; + + /* Skip any leading white space. */ + for (offset = buffer; offset <= buffer+len && isspace((int)*offset); + offset++); + /* Kill any ending white space. */ + for (; len >= 0 && isspace((int)buffer[len]); len--); + + /* If there's a leading brace, kill it and the ending one. */ + if (offset[0] == '[') { + if (buffer[len] != ']') { + fprintf(stderr, "ERROR: Unbalanced braces.\n"); + [parser free]; [string free]; + return nil; + } + offset++; len--; + + /* Do the whitespace shuffle again. */ + for (; len >= 0 && isspace((int)buffer[len]); len--); + } + + while (offset < buffer+len) { + DataObject *dataObj; + int strLen; + + /* Do the whitespace shuffle. */ + for (; offset <= buffer+len && isspace((int)*offset); offset++); + + strLen = [parser getLineLenFrom: offset to: buffer+len]; + [string setStr: offset withLength: strLen]; + offset += strLen + 1; + + /* Parse the data element, then add it to our list. */ + dataObj = [parser getDataFrom: string]; + if (dataObj == nil) { + [parser free]; [string free]; + return nil; + } + [self addChild: dataObj]; + } + + [parser free]; [string free]; + return self; +} + +-(int) +numObjects +{ + return numChildren; +} + +-objectAt: (int)index +{ + if (index >= numChildren) + return nil; + return data[index]; +} +@end diff --git a/libconfig/.svn/text-base/BuffIO.h.svn-base b/libconfig/.svn/text-base/BuffIO.h.svn-base new file mode 100644 index 0000000..d58a0a3 --- /dev/null +++ b/libconfig/.svn/text-base/BuffIO.h.svn-base @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef BUFFIO_H +# define BUFFIO_H + +#include <Object.h> + +#include <sys/types.h> + +@interface BuffIO: Object +{ + char *file; + char *curOff; + off_t fileLen; + char EOL; +} + +-init: (const char *)fileName; +-free; +-(char *)getCurOff; +-(off_t)getLength; +-setEOL: (char)delim; +@end +#endif diff --git a/libconfig/.svn/text-base/BuffIO.m.svn-base b/libconfig/.svn/text-base/BuffIO.m.svn-base new file mode 100644 index 0000000..f7a5408 --- /dev/null +++ b/libconfig/.svn/text-base/BuffIO.m.svn-base @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ + +#include "BuffIO.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> + +@implementation BuffIO +-init: (const char *)fileName +{ + struct stat sb; + int confFd; + + confFd = open(fileName, O_RDONLY, 0); + if (confFd == -1) { + fprintf(stderr, "ERROR: couldn't open config file %s: %s.\n", + fileName, strerror(errno)); + return nil; + } + if (fstat(confFd, &sb) == -1) { + fprintf(stderr, "ERROR: couldn't stat config file %s: %s.\n", + fileName, strerror(errno)); + return nil; + } + fileLen = sb.st_size; + file = mmap(NULL, fileLen, PROT_READ, MAP_PRIVATE, confFd, 0); + if (file == MAP_FAILED) { + fprintf(stderr, "ERROR: couldn't mmap config file %s: %s.\n", + fileName, strerror(errno)); + return nil; + } + close(confFd); + + curOff = file; + EOL = '\n'; + + return self; +} + +-free +{ + munmap(file, fileLen); + return [super free]; +} + +-(char *) +getCurOff +{ + return curOff; +} + +-(off_t) +getLength +{ + return fileLen; +} + +-setEOL: (char)delim +{ + EOL = delim; + return self; +} +@end diff --git a/libconfig/.svn/text-base/COPYRIGHT.svn-base b/libconfig/.svn/text-base/COPYRIGHT.svn-base new file mode 100644 index 0000000..a61dc39 --- /dev/null +++ b/libconfig/.svn/text-base/COPYRIGHT.svn-base @@ -0,0 +1,27 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ diff --git a/libconfig/.svn/text-base/Data.h.svn-base b/libconfig/.svn/text-base/Data.h.svn-base new file mode 100644 index 0000000..966310f --- /dev/null +++ b/libconfig/.svn/text-base/Data.h.svn-base @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef DATA_H +# define DATA_H + +#include "String.h" + +#include <Object.h> + +#include <sys/types.h> + +#define MALLOC_GRANULARITY 10 /* Malloc for every 10 entries. */ + +/* + * Generic Entry and Data objects. + */ +@interface DataObject: Object +-dealloc; +-(char *)createCStr; +-(String *)createStr; +-setFromBuffer: (const char *)buffer withLength: (int)len; +@end + +@interface DictEntry: Object +{ + String *key; + DataObject *data; + DictEntry *super; +} + +-init; +-setKey: keyName; +-setData: dataPtr; +-getKey; +-getData; +@end +#endif diff --git a/libconfig/.svn/text-base/Data.m.svn-base b/libconfig/.svn/text-base/Data.m.svn-base new file mode 100644 index 0000000..3b48c7a --- /dev/null +++ b/libconfig/.svn/text-base/Data.m.svn-base @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "Data.h" +#include "Parser.h" +#include "String.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +@implementation DataObject +-dealloc +{ + free(self); + return nil; +} + +-(char *)createCStr +{ + return NULL; +} + +-(String *)createStr +{ + return nil; +} + +-setFromBuffer: (const char *)buffer withLength: (int)len +{ + return self; +} +@end + +@implementation DictEntry +-init +{ + self = [super init]; + key = NULL; data = NULL; + return self; +} + +-setKey: (String *)keyStr +{ + key = keyStr; + return self; +} + +-setData: (DataObject *)dataPtr +{ + data = dataPtr; + return self; +} + +-getKey +{ + return key; +} + +-getData +{ + return data; +} +@end diff --git a/libconfig/.svn/text-base/DictData.h.svn-base b/libconfig/.svn/text-base/DictData.h.svn-base new file mode 100644 index 0000000..52dfc0d --- /dev/null +++ b/libconfig/.svn/text-base/DictData.h.svn-base @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef DICTDATA_H +# define DICTDATA_H + +#include "Data.h" + +@interface DictData: DataObject +{ + id *data; + int numChildren; + int curObj; +} + +-free; +-addChild: child; +-delChild: (const char *)keyName; +-findChild: (const char *)keyName; +-firstObject; +-nextObject; +@end +#endif diff --git a/libconfig/.svn/text-base/DictData.m.svn-base b/libconfig/.svn/text-base/DictData.m.svn-base new file mode 100644 index 0000000..8620d7c --- /dev/null +++ b/libconfig/.svn/text-base/DictData.m.svn-base @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "DictData.h" +#include "Parser.h" +#include "String.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +@implementation DictData +-init +{ + self = [super init]; + + numChildren = 0; + curObj = 0; + data = malloc(MALLOC_GRANULARITY * sizeof(DataObject *)); + if (!data) { + fprintf(stderr, "ERROR: couldn't allocate memory: %s.\n", + strerror(errno)); + return nil; + } + + return self; +} + +-free +{ + int i; + + fprintf(stderr, "DEBUG: freeing dict\n"); + for (i = 0; i < numChildren; i++) + [data[i] free]; + free(data); + [super free]; + + return nil; +} + +-addChild: child +{ + /* Allocate additional space for children pointers, if required. */ + if (numChildren % MALLOC_GRANULARITY == 0) { + /* TODO: fail gracefully. */ + data = realloc(data, (numChildren+MALLOC_GRANULARITY) * + sizeof(DictEntry *)); + if (!data) { + fprintf(stderr, + "ERROR: couldn't allocate memory: %s.\n", + strerror(errno)); + return nil; + } + } + + data[numChildren] = child; + + numChildren++; + return self; +} + +-setFromBuffer: (const char *)buffer withLength: (int)len +{ + Parser *parser; + String *string; + const char *offset; + + self = [super init]; + parser = [Parser new]; + string = [[String new] init]; + if (parser == nil || string == nil) + return nil; + + if (buffer[len] == '\0') + len--; + + /* Skip any leading white space. */ + for (offset = buffer; offset <= buffer+len && isspace((int)*offset); + offset++); + /* Kill any ending white space. */ + for (; len >= 0 && isspace((int)buffer[len]); len--); + + /* If there's a leading brace, kill it and the ending one. */ + if (offset[0] == '{') { + if (buffer[len] != '}') { + fprintf(stderr, "ERROR: Unbalanced braces.\n"); + [parser free]; [string free]; + return nil; + } + offset++; len--; + + /* Do the whitespace shuffle again. */ + for (; len >= 0 && isspace((int)buffer[len]); len--); + } + + while (offset < buffer+len) { + DataObject *dataObj; + DictEntry *dictEntry; + String *key; + char *sep; + int strLen; + + /* Do the whitespace shuffle. */ + for (; offset <= buffer+len && isspace((int)*offset); offset++); + + /* Get the key element. */ + sep = strchr(offset, '='); + if (!sep) { + fprintf(stderr, "ERROR: No equals sign!\n"); + return nil; + } + for (sep--; sep > offset && isspace((int)*sep); sep--); + key = [[[String new] init] setStr: offset + withLength: (sep-offset+1)]; + + /* Get the data element. */ + offset = strchr(offset, '='); + for(offset++; offset < buffer+len && isspace((int)*offset); + offset++); + strLen = [parser getLineLenFrom: offset to: buffer+len]; + [string setStr: offset withLength: strLen]; + offset += strLen + 1; + + /* Parse the data element, then add it to our list. */ + dataObj = [parser getDataFrom: string]; + if (dataObj == nil) { + fprintf(stderr, + "ERROR: Couldn't parse data for node `%s'.\n", + [key getStr]); + [parser free]; [string free]; + return nil; + } + + dictEntry = [[DictEntry new] setKey: key]; + if (dictEntry == nil) { + fprintf(stderr, + "ERROR: Couldn't create node `%s'.\n", + [key getStr]); + [parser free]; [string free]; + return nil; + } + [dictEntry setData: dataObj]; + [self addChild: dictEntry]; + } + + [parser free]; [string free]; + return self; +} + +-delChild: (const char *)keyName +{ + return self; +} + +-findChild: (const char *)keyName +{ + int i; + + for (i = 0; i < numChildren; i++) + if (!strcmp([[data[i] getKey] getStr], keyName)) + return data[i]; + return nil; +} + +-firstObject +{ + curObj = 0; + return [self nextObject]; +} + +-nextObject +{ + DictEntry *obj; + + if (curObj >= numChildren) + return nil; + obj = data[curObj]; + curObj++; + return obj; +} +@end diff --git a/libconfig/.svn/text-base/Makefile.svn-base b/libconfig/.svn/text-base/Makefile.svn-base new file mode 100644 index 0000000..9fca5ac --- /dev/null +++ b/libconfig/.svn/text-base/Makefile.svn-base @@ -0,0 +1,11 @@ +# $Id: Makefile,v 1.1 2001/10/04 23:57:55 shmit Exp $ + +CONFIGOBJS= ArrayData.o BuffIO.o Data.o DictData.o NumData.o Parser.o \ + String.o StringData.o config.o + +libconfig.a: ${CONFIGOBJS} + ar r $@ ${CONFIGOBJS} + ranlib $@ + +MKDIR= ../Makefiles +include ${MKDIR}/build diff --git a/libconfig/.svn/text-base/NumData.h.svn-base b/libconfig/.svn/text-base/NumData.h.svn-base new file mode 100644 index 0000000..a8c2810 --- /dev/null +++ b/libconfig/.svn/text-base/NumData.h.svn-base @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef NUMDATA_H +# define NUMDATA_H + +#include "Data.h" + +@interface NumData: DataObject +{ + long data; +} +-(long)getNum; +@end +#endif diff --git a/libconfig/.svn/text-base/NumData.m.svn-base b/libconfig/.svn/text-base/NumData.m.svn-base new file mode 100644 index 0000000..68f6bfa --- /dev/null +++ b/libconfig/.svn/text-base/NumData.m.svn-base @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "NumData.h" +#include "Parser.h" +#include "String.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +@implementation NumData +-init +{ + self = [super init]; + return self; +} + +-(String *) +createStr +{ + char buffer[1024]; + + snprintf(buffer, sizeof(buffer), "%ld", data); + return [[String new] setStr: buffer]; +} + +-setFromBuffer: (const char *)buffer withLength: (int)len +{ + char *endPtr; + + data = strtol(buffer, &endPtr, 0); + if (*endPtr) { + fprintf(stderr, "ERROR: `%s' is not a number.\n", buffer); + return nil; + } + + return self; +} + +-(long) +getNum +{ + return data; +} +@end diff --git a/libconfig/.svn/text-base/Parser.h.svn-base b/libconfig/.svn/text-base/Parser.h.svn-base new file mode 100644 index 0000000..963a78a --- /dev/null +++ b/libconfig/.svn/text-base/Parser.h.svn-base @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef PARSER_H +# define PARSER_H + +#include "Data.h" +#include "String.h" + +#include <Object.h> + +@interface Parser: Object +-free; +-init; +-(DataObject *)getDataFrom: (String *)line; +-(int)getLineLenFrom: (const char *)startAddr to: (const char *)endAddr; +@end +#endif diff --git a/libconfig/.svn/text-base/Parser.m.svn-base b/libconfig/.svn/text-base/Parser.m.svn-base new file mode 100644 index 0000000..f95cb3d --- /dev/null +++ b/libconfig/.svn/text-base/Parser.m.svn-base @@ -0,0 +1,95 @@ +#include "Parser.h" +#include "ArrayData.h" +#include "DictData.h" +#include "NumData.h" +#include "StringData.h" +#include "String.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +@implementation Parser +-(int) +getLineLenFrom: (const char *)startAddr to: (const char *)endAddr +{ + int len; + char quote = '\0'; + int frenchBraces = 0, squareBraces = 0; + + for (len = 0; startAddr+len < endAddr; len++) { + if (!quote && !frenchBraces && !squareBraces && + *(startAddr+len) == ';') + break; + + switch (*(startAddr+len)) { + case '{': + frenchBraces++; + break; + case '}': + if (!frenchBraces) + fprintf(stderr, + "WARNING: found `}' without `{'.\n"); + else + frenchBraces--; + break; + case '[': + squareBraces++; + break; + case ']': + if (!squareBraces) + fprintf(stderr, + "WARNING: found ']' without '['.\n"); + else + squareBraces--; + break; + case '"': + if (!quote) + quote = *(startAddr+len); + else + quote = '\0'; + break; + } + } + + return len; +} + +-init +{ + return self; +} + +-free +{ + return [super free]; +} + +-(DataObject *) +getDataFrom: (String *)dataStr +{ + const char *dataBuff; + id dataElem; + + dataBuff = [dataStr getStr]; + + /* Figure out what type of node to allocate. */ + switch (dataBuff[0]) { + case '{': + dataElem = [[DictData new] init]; + break; + case '[': + dataElem = [[ArrayData new] init]; + break; + case '"': + dataElem = [[StringData new] init]; + break; + default: + dataElem = [[NumData new] init]; + break; + } + + return [dataElem setFromBuffer: dataBuff withLength: [dataStr getLen]]; +} +@end diff --git a/libconfig/.svn/text-base/String.h.svn-base b/libconfig/.svn/text-base/String.h.svn-base new file mode 100644 index 0000000..ab0aaad --- /dev/null +++ b/libconfig/.svn/text-base/String.h.svn-base @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef STRING_H +# define STRING_H + +#include <Object.h> + +@interface String: Object +{ + char *data; + int len; +} + +-init; +-free; +-setStr: (const char *)stringData withLength: (int)length; +-setStr: (const char *)stringData; +-(int)getLen; +-(char *)getStr; +@end +#endif diff --git a/libconfig/.svn/text-base/String.m.svn-base b/libconfig/.svn/text-base/String.m.svn-base new file mode 100644 index 0000000..9a0bc5a --- /dev/null +++ b/libconfig/.svn/text-base/String.m.svn-base @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "String.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +@implementation String +-init +{ + self = [super init]; + data = NULL; + return self; +} + +-free +{ + free(data); + return [super free]; +} + +-setStr: (const char *)stringData withLength: (int)length +{ + if (data) + free(data); + + data = malloc((length+1)*sizeof(char)); + if (!data) { + fprintf(stderr, "ERROR: Couldn't allocate memory: %s.\n", + strerror(errno)); + return nil; + } + + memcpy(data, stringData, length); + data[length] = '\0'; + len = length; + return self; +} + +-setStr: (const char *)stringData +{ + return [self setStr: stringData withLength: strlen(stringData)]; +} + +-(int) +getLen +{ + return len; +} + +-(char *) +getStr +{ + return data; +} +@end diff --git a/libconfig/.svn/text-base/StringData.h.svn-base b/libconfig/.svn/text-base/StringData.h.svn-base new file mode 100644 index 0000000..80c4d26 --- /dev/null +++ b/libconfig/.svn/text-base/StringData.h.svn-base @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef STRINGDATA_H +# define STRINGDATA_H + +#include "Data.h" +#include "String.h" + +@interface StringData: DataObject +{ + String *data; +} + +-free; +@end +#endif diff --git a/libconfig/.svn/text-base/StringData.m.svn-base b/libconfig/.svn/text-base/StringData.m.svn-base new file mode 100644 index 0000000..1c02ac5 --- /dev/null +++ b/libconfig/.svn/text-base/StringData.m.svn-base @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "conf.h" + +#include "StringData.h" +#include "Parser.h" +#include "String.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#if NEED_STRINGS +#include <strings.h> +#endif + +@implementation StringData +-init +{ + self = [super init]; + data = [[String new] init]; + return self; +} + +-free +{ + [data free]; + [super free]; + return self; +} + +-(char *) +createCStr +{ + char *buffer; + + buffer = malloc(([data getLen]+1) * sizeof(char)); + if (!buffer) { + fprintf(stderr, "ERROR: Couldn't allocate buffer: %s.\n", + strerror(errno)); + return NULL; + } + + strcpy(buffer, [data getStr]); + return buffer; +} + +-(String *) +createStr +{ + String *str; + char *buffer; + + buffer = [self createCStr]; + if (buffer == NULL) + return nil; + + str = [[[String new] init] setStr: buffer]; + free(buffer); + + return str; +} + +-setFromBuffer: (const char *)buffer withLength: (int)len +{ + const char *startPtr, *endPtr; + + startPtr = index(buffer, '"'); + if (!startPtr) { + fprintf(stderr, "ERROR: No opening quote for string.\n"); + return nil; + } + startPtr++; + + for (endPtr = buffer+len; endPtr > startPtr; endPtr--) + if (*endPtr == '"') + break; + + if (endPtr == startPtr) { + fprintf(stderr, "ERROR: No ending quote for string.\n"); + return nil; + } + endPtr--; + + [data setStr: startPtr withLength: endPtr-startPtr+1]; + return self; +} +@end diff --git a/libconfig/.svn/text-base/config.m.svn-base b/libconfig/.svn/text-base/config.m.svn-base new file mode 100644 index 0000000..b0d13a9 --- /dev/null +++ b/libconfig/.svn/text-base/config.m.svn-base @@ -0,0 +1,287 @@ +#include "conf.h" +#include "config.h" +#include "nastipc.h" +#include "thread.h" + +#include "BuffIO.h" +#include "ArrayData.h" +#include "DictData.h" +#include "NumData.h" +#include "StringData.h" + +#include <netdb.h> +#include <stdlib.h> + +RCSID("$Id: config.m,v 1.5 2001/11/09 15:54:38 shmit Exp $"); + +/* + * Global variables. + */ +static DictData *root; +char config_filen[MAXPATHLEN]; +struct nast_config config; + +static int +config_read(const char *filename) +{ + BuffIO *confFile; + + confFile = [[[BuffIO new] init: filename] setEOL: ';']; + if (confFile == nil) { + fprintf(stderr, "ERROR: Couldn't load config file."); + return -1; + } + + root = [[DictData new] setFromBuffer: [confFile getCurOff] + withLength: [confFile getLength]]; + + /* We've duplicated all the data in here into private storage. */ + [confFile free]; + + if (root == nil) { + fprintf(stderr, "ERROR: Couldn't parse config file."); + return -1; + } + return 0; +} + +static int +get_val(const char *name, void *dst, enum data_type type) +{ + id node; + + node = [[root findChild: name] getData]; + if (node == nil) + return 0; + + switch (type) { + case NUMBER: + if (![node isKindOf: [NumData class]]) { + fprintf(stderr, "Node `%s' in `%s' should be a number.", + name, config_filen); + return -1; + } + *(int *)dst = [node getNum]; + break; + case STRING: + if (![node isKindOf: [StringData class]]) { + fprintf(stderr, "Node `%s' in `%s' should be a string.", + name, config_filen); + return -1; + } + *(char **)dst = [node createCStr]; + break; + case ARRAY: + fprintf(stderr, "ERROR: Can't load array into C yet."); + return -1; + case DICTIONARY: + fprintf(stderr, "ERROR: Can't load dictionary into C yet."); + return -1; + default: + fprintf(stderr, "ERROR: Don't know what to do with type `%d'.", + type); + return -1; + } + + return 0; +} + +/* + * Sets configuration variables to defaults, in case they're not set + * elsewhere. + */ +void +config_setdefaults() +{ + /* Set the defaults. */ + config.description = "Description not set in config file."; + config.nast_dir = DATADIR; + config.nast_sock = NASTHOLE; + config.nast_cdb_file = "nast.cdb"; + config.mysql_host = DBHOST; + config.mysql_user = DBUSER; + config.mysql_pass = DBPASS; + config.nofork_flag = 0; + config.null_cache_timeout = 60; + config.tcp_port = 31337; + + return; +} + +/* + * Initializes configuration variables from config file. + */ +int +config_init() +{ + snprintf(config_filen, sizeof(config_filen), + "%s/nastd.conf", config.nast_dir); + if (config_read(config_filen) == -1) + return -1; + + /* + * Now grab all the top-level config information. + */ + if (get_val("description", &config.description, STRING) == -1) + return -1; + + if (get_val("nast_dir", &config.nast_dir, STRING) == -1) + return -1; + + if (get_val("nast_sock", &config.nast_sock, STRING) == -1) + return -1; + + if (get_val("nast_cdb_file", &config.nast_cdb_file, STRING) == -1) + return -1; + + if (get_val("mysql_host", &config.mysql_host, STRING) == -1) + return -1; + + if (get_val("mysql_user", &config.mysql_user, STRING) == -1) + return -1; + + if (get_val("mysql_pass", &config.mysql_pass, STRING) == -1) + return -1; + + if (get_val("null_cache_timeout", &config.null_cache_timeout, + NUMBER) == -1) + return -1; + + if (get_val("tcp_port", &config.tcp_port, NUMBER) == -1) + return -1; + + return 0; +} + +void +config_delete() +{ + [root free]; +} + +static enum data_type +getctype(id node) +{ + if ([node isKindOf: [StringData class]]) + return STRING; + else if ([node isKindOf: [NumData class]]) + return NUMBER; + else if ([node isKindOf: [ArrayData class]]) + return ARRAY; + else if ([node isKindOf: [DictData class]]) + return DICTIONARY; + else { + return -1; + } +} + +void * +config_find(void *root_node, const char *name, enum data_type *type) +{ + id rootNode, dstNode; + + if (root_node == NULL) + root_node = root; + + rootNode = (id)root_node; + if ([rootNode isKindOf: [DictData class]] == NO) { + fprintf(stderr, "Trying to find `%s' in non-dictionary.", name); + return NULL; + } + + dstNode = [[rootNode findChild: name] getData]; + if (dstNode == nil) + return NULL; + *type = getctype(dstNode); + return dstNode; +} + +void * +config_arrayitemat(void *array, int index, enum data_type *type) +{ + id arrayNode, dstNode; + + if (array == NULL) + return NULL; + + arrayNode = (id)array; + if ([arrayNode isKindOf: [ArrayData class]] == NO) { + fprintf(stderr, "Trying to index in non-array."); + return NULL; + } + + if (index >= [arrayNode numObjects]) + return NULL; + + dstNode = [arrayNode objectAt: index]; + if (dstNode == nil) + return NULL; + *type = getctype(dstNode); + return dstNode; +} + +void * +config_dictitemat(void *dict, const char *name, enum data_type *type) +{ + id dictNode, dstNode; + + if (dict == NULL) + return NULL; + + dictNode = (id)dict; + if ([dictNode isKindOf: [DictData class]] == NO) { + fprintf(stderr, "Trying to find `%s' in non-dictionary.", name); + return NULL; + } + + dstNode = [[dictNode findChild: name] getData]; + if (dstNode == nil) + return NULL; + *type = getctype(dstNode); + return dstNode; +} + +void * +getdata(void *itemref, void *dst, enum data_type want_type) +{ + id item; + + if (itemref == NULL) + return NULL; + + item = (id)itemref; + if ([item isKindOf: [DataObject class]] == NO) { + fprintf(stderr, "Can only deref DataObject types " + "or sub-classes."); + return NULL; + } + + switch (want_type) { + case NUMBER: + if ([item isKindOf: [NumData class]] == NO) + return NULL; + *(int *)dst = [item getNum]; + break; + case STRING: + if ([item isKindOf: [StringData class]] == NO) + return NULL; + *(char **)dst = [item createCStr]; + break; + case ARRAY: + if ([item isKindOf: [ArrayData class]] == NO) + return NULL; + dst = [item getData]; + break; + case DICTIONARY: + if ([item isKindOf: [DictData class]] == NO) + return NULL; + dst = [item getData]; + break; + default: + fprintf(stderr, + "Can't deref type `%d': unknown type.", want_type); + return NULL; + } + + return dst; +} diff --git a/libconfig/ArrayData.h b/libconfig/ArrayData.h new file mode 100644 index 0000000..246803e --- /dev/null +++ b/libconfig/ArrayData.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef ARRAYDATA_H +# define ARRAYDATA_H + +#include "Data.h" + +@interface ArrayData: DataObject +{ + id *data; + int numChildren; + int curObj; +} +-free; +-(int)numObjects; +-addChild: child; +-objectAt: (int)index; +@end +#endif diff --git a/libconfig/ArrayData.m b/libconfig/ArrayData.m new file mode 100644 index 0000000..dfee1e7 --- /dev/null +++ b/libconfig/ArrayData.m @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "ArrayData.h" +#include "Parser.h" +#include "String.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +@implementation ArrayData +-init +{ + self = [super init]; + + numChildren = 0; + curObj = 0; + data = malloc(MALLOC_GRANULARITY * sizeof(DictEntry *)); + if (!data) { + fprintf(stderr, "ERROR: couldn't allocate memory: %s.\n", + strerror(errno)); + return nil; + } + + return self; +} + +-free +{ + int i; + + fprintf(stderr, "DEBUG: freeing array\n"); + for (i = 0; i < numChildren; i++) + [data[i] free]; + free(data); + [super free]; + + return nil; +} + +-addChild: child +{ + /* Allocate additional space for children pointers, if required. */ + if (numChildren % MALLOC_GRANULARITY == 0) { + /* TODO: fail gracefully. */ + data = realloc(data, (numChildren+MALLOC_GRANULARITY) * + sizeof(DataObject *)); + if (!data) { + fprintf(stderr, + "ERROR: couldn't allocate memory: %s.\n", + strerror(errno)); + return nil; + } + } + + data[numChildren] = child; + + numChildren++; + return self; +} + +-setFromBuffer: (const char *)buffer withLength: (int)len +{ + Parser *parser; + String *string; + const char *offset; + + self = [super init]; + parser = [Parser new]; + string = [[String new] init]; + if (parser == nil || string == nil) + return nil; + + if (buffer[len] == '\0') + len--; + + /* Skip any leading white space. */ + for (offset = buffer; offset <= buffer+len && isspace((int)*offset); + offset++); + /* Kill any ending white space. */ + for (; len >= 0 && isspace((int)buffer[len]); len--); + + /* If there's a leading brace, kill it and the ending one. */ + if (offset[0] == '[') { + if (buffer[len] != ']') { + fprintf(stderr, "ERROR: Unbalanced braces.\n"); + [parser free]; [string free]; + return nil; + } + offset++; len--; + + /* Do the whitespace shuffle again. */ + for (; len >= 0 && isspace((int)buffer[len]); len--); + } + + while (offset < buffer+len) { + DataObject *dataObj; + int strLen; + + /* Do the whitespace shuffle. */ + for (; offset <= buffer+len && isspace((int)*offset); offset++); + + strLen = [parser getLineLenFrom: offset to: buffer+len]; + [string setStr: offset withLength: strLen]; + offset += strLen + 1; + + /* Parse the data element, then add it to our list. */ + dataObj = [parser getDataFrom: string]; + if (dataObj == nil) { + [parser free]; [string free]; + return nil; + } + [self addChild: dataObj]; + } + + [parser free]; [string free]; + return self; +} + +-(int) +numObjects +{ + return numChildren; +} + +-objectAt: (int)index +{ + if (index >= numChildren) + return nil; + return data[index]; +} +@end diff --git a/libconfig/BuffIO.h b/libconfig/BuffIO.h new file mode 100644 index 0000000..d58a0a3 --- /dev/null +++ b/libconfig/BuffIO.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef BUFFIO_H +# define BUFFIO_H + +#include <Object.h> + +#include <sys/types.h> + +@interface BuffIO: Object +{ + char *file; + char *curOff; + off_t fileLen; + char EOL; +} + +-init: (const char *)fileName; +-free; +-(char *)getCurOff; +-(off_t)getLength; +-setEOL: (char)delim; +@end +#endif diff --git a/libconfig/BuffIO.m b/libconfig/BuffIO.m new file mode 100644 index 0000000..f7a5408 --- /dev/null +++ b/libconfig/BuffIO.m @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ + +#include "BuffIO.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> + +@implementation BuffIO +-init: (const char *)fileName +{ + struct stat sb; + int confFd; + + confFd = open(fileName, O_RDONLY, 0); + if (confFd == -1) { + fprintf(stderr, "ERROR: couldn't open config file %s: %s.\n", + fileName, strerror(errno)); + return nil; + } + if (fstat(confFd, &sb) == -1) { + fprintf(stderr, "ERROR: couldn't stat config file %s: %s.\n", + fileName, strerror(errno)); + return nil; + } + fileLen = sb.st_size; + file = mmap(NULL, fileLen, PROT_READ, MAP_PRIVATE, confFd, 0); + if (file == MAP_FAILED) { + fprintf(stderr, "ERROR: couldn't mmap config file %s: %s.\n", + fileName, strerror(errno)); + return nil; + } + close(confFd); + + curOff = file; + EOL = '\n'; + + return self; +} + +-free +{ + munmap(file, fileLen); + return [super free]; +} + +-(char *) +getCurOff +{ + return curOff; +} + +-(off_t) +getLength +{ + return fileLen; +} + +-setEOL: (char)delim +{ + EOL = delim; + return self; +} +@end diff --git a/libconfig/COPYRIGHT b/libconfig/COPYRIGHT new file mode 100644 index 0000000..a61dc39 --- /dev/null +++ b/libconfig/COPYRIGHT @@ -0,0 +1,27 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ diff --git a/libconfig/Data.h b/libconfig/Data.h new file mode 100644 index 0000000..966310f --- /dev/null +++ b/libconfig/Data.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef DATA_H +# define DATA_H + +#include "String.h" + +#include <Object.h> + +#include <sys/types.h> + +#define MALLOC_GRANULARITY 10 /* Malloc for every 10 entries. */ + +/* + * Generic Entry and Data objects. + */ +@interface DataObject: Object +-dealloc; +-(char *)createCStr; +-(String *)createStr; +-setFromBuffer: (const char *)buffer withLength: (int)len; +@end + +@interface DictEntry: Object +{ + String *key; + DataObject *data; + DictEntry *super; +} + +-init; +-setKey: keyName; +-setData: dataPtr; +-getKey; +-getData; +@end +#endif diff --git a/libconfig/Data.m b/libconfig/Data.m new file mode 100644 index 0000000..3b48c7a --- /dev/null +++ b/libconfig/Data.m @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "Data.h" +#include "Parser.h" +#include "String.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +@implementation DataObject +-dealloc +{ + free(self); + return nil; +} + +-(char *)createCStr +{ + return NULL; +} + +-(String *)createStr +{ + return nil; +} + +-setFromBuffer: (const char *)buffer withLength: (int)len +{ + return self; +} +@end + +@implementation DictEntry +-init +{ + self = [super init]; + key = NULL; data = NULL; + return self; +} + +-setKey: (String *)keyStr +{ + key = keyStr; + return self; +} + +-setData: (DataObject *)dataPtr +{ + data = dataPtr; + return self; +} + +-getKey +{ + return key; +} + +-getData +{ + return data; +} +@end diff --git a/libconfig/DictData.h b/libconfig/DictData.h new file mode 100644 index 0000000..52dfc0d --- /dev/null +++ b/libconfig/DictData.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef DICTDATA_H +# define DICTDATA_H + +#include "Data.h" + +@interface DictData: DataObject +{ + id *data; + int numChildren; + int curObj; +} + +-free; +-addChild: child; +-delChild: (const char *)keyName; +-findChild: (const char *)keyName; +-firstObject; +-nextObject; +@end +#endif diff --git a/libconfig/DictData.m b/libconfig/DictData.m new file mode 100644 index 0000000..8620d7c --- /dev/null +++ b/libconfig/DictData.m @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "DictData.h" +#include "Parser.h" +#include "String.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +@implementation DictData +-init +{ + self = [super init]; + + numChildren = 0; + curObj = 0; + data = malloc(MALLOC_GRANULARITY * sizeof(DataObject *)); + if (!data) { + fprintf(stderr, "ERROR: couldn't allocate memory: %s.\n", + strerror(errno)); + return nil; + } + + return self; +} + +-free +{ + int i; + + fprintf(stderr, "DEBUG: freeing dict\n"); + for (i = 0; i < numChildren; i++) + [data[i] free]; + free(data); + [super free]; + + return nil; +} + +-addChild: child +{ + /* Allocate additional space for children pointers, if required. */ + if (numChildren % MALLOC_GRANULARITY == 0) { + /* TODO: fail gracefully. */ + data = realloc(data, (numChildren+MALLOC_GRANULARITY) * + sizeof(DictEntry *)); + if (!data) { + fprintf(stderr, + "ERROR: couldn't allocate memory: %s.\n", + strerror(errno)); + return nil; + } + } + + data[numChildren] = child; + + numChildren++; + return self; +} + +-setFromBuffer: (const char *)buffer withLength: (int)len +{ + Parser *parser; + String *string; + const char *offset; + + self = [super init]; + parser = [Parser new]; + string = [[String new] init]; + if (parser == nil || string == nil) + return nil; + + if (buffer[len] == '\0') + len--; + + /* Skip any leading white space. */ + for (offset = buffer; offset <= buffer+len && isspace((int)*offset); + offset++); + /* Kill any ending white space. */ + for (; len >= 0 && isspace((int)buffer[len]); len--); + + /* If there's a leading brace, kill it and the ending one. */ + if (offset[0] == '{') { + if (buffer[len] != '}') { + fprintf(stderr, "ERROR: Unbalanced braces.\n"); + [parser free]; [string free]; + return nil; + } + offset++; len--; + + /* Do the whitespace shuffle again. */ + for (; len >= 0 && isspace((int)buffer[len]); len--); + } + + while (offset < buffer+len) { + DataObject *dataObj; + DictEntry *dictEntry; + String *key; + char *sep; + int strLen; + + /* Do the whitespace shuffle. */ + for (; offset <= buffer+len && isspace((int)*offset); offset++); + + /* Get the key element. */ + sep = strchr(offset, '='); + if (!sep) { + fprintf(stderr, "ERROR: No equals sign!\n"); + return nil; + } + for (sep--; sep > offset && isspace((int)*sep); sep--); + key = [[[String new] init] setStr: offset + withLength: (sep-offset+1)]; + + /* Get the data element. */ + offset = strchr(offset, '='); + for(offset++; offset < buffer+len && isspace((int)*offset); + offset++); + strLen = [parser getLineLenFrom: offset to: buffer+len]; + [string setStr: offset withLength: strLen]; + offset += strLen + 1; + + /* Parse the data element, then add it to our list. */ + dataObj = [parser getDataFrom: string]; + if (dataObj == nil) { + fprintf(stderr, + "ERROR: Couldn't parse data for node `%s'.\n", + [key getStr]); + [parser free]; [string free]; + return nil; + } + + dictEntry = [[DictEntry new] setKey: key]; + if (dictEntry == nil) { + fprintf(stderr, + "ERROR: Couldn't create node `%s'.\n", + [key getStr]); + [parser free]; [string free]; + return nil; + } + [dictEntry setData: dataObj]; + [self addChild: dictEntry]; + } + + [parser free]; [string free]; + return self; +} + +-delChild: (const char *)keyName +{ + return self; +} + +-findChild: (const char *)keyName +{ + int i; + + for (i = 0; i < numChildren; i++) + if (!strcmp([[data[i] getKey] getStr], keyName)) + return data[i]; + return nil; +} + +-firstObject +{ + curObj = 0; + return [self nextObject]; +} + +-nextObject +{ + DictEntry *obj; + + if (curObj >= numChildren) + return nil; + obj = data[curObj]; + curObj++; + return obj; +} +@end diff --git a/libconfig/Makefile b/libconfig/Makefile new file mode 100644 index 0000000..9fca5ac --- /dev/null +++ b/libconfig/Makefile @@ -0,0 +1,11 @@ +# $Id: Makefile,v 1.1 2001/10/04 23:57:55 shmit Exp $ + +CONFIGOBJS= ArrayData.o BuffIO.o Data.o DictData.o NumData.o Parser.o \ + String.o StringData.o config.o + +libconfig.a: ${CONFIGOBJS} + ar r $@ ${CONFIGOBJS} + ranlib $@ + +MKDIR= ../Makefiles +include ${MKDIR}/build diff --git a/libconfig/NumData.h b/libconfig/NumData.h new file mode 100644 index 0000000..a8c2810 --- /dev/null +++ b/libconfig/NumData.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef NUMDATA_H +# define NUMDATA_H + +#include "Data.h" + +@interface NumData: DataObject +{ + long data; +} +-(long)getNum; +@end +#endif diff --git a/libconfig/NumData.m b/libconfig/NumData.m new file mode 100644 index 0000000..68f6bfa --- /dev/null +++ b/libconfig/NumData.m @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "NumData.h" +#include "Parser.h" +#include "String.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +@implementation NumData +-init +{ + self = [super init]; + return self; +} + +-(String *) +createStr +{ + char buffer[1024]; + + snprintf(buffer, sizeof(buffer), "%ld", data); + return [[String new] setStr: buffer]; +} + +-setFromBuffer: (const char *)buffer withLength: (int)len +{ + char *endPtr; + + data = strtol(buffer, &endPtr, 0); + if (*endPtr) { + fprintf(stderr, "ERROR: `%s' is not a number.\n", buffer); + return nil; + } + + return self; +} + +-(long) +getNum +{ + return data; +} +@end diff --git a/libconfig/Parser.h b/libconfig/Parser.h new file mode 100644 index 0000000..963a78a --- /dev/null +++ b/libconfig/Parser.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef PARSER_H +# define PARSER_H + +#include "Data.h" +#include "String.h" + +#include <Object.h> + +@interface Parser: Object +-free; +-init; +-(DataObject *)getDataFrom: (String *)line; +-(int)getLineLenFrom: (const char *)startAddr to: (const char *)endAddr; +@end +#endif diff --git a/libconfig/Parser.m b/libconfig/Parser.m new file mode 100644 index 0000000..f95cb3d --- /dev/null +++ b/libconfig/Parser.m @@ -0,0 +1,95 @@ +#include "Parser.h" +#include "ArrayData.h" +#include "DictData.h" +#include "NumData.h" +#include "StringData.h" +#include "String.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +@implementation Parser +-(int) +getLineLenFrom: (const char *)startAddr to: (const char *)endAddr +{ + int len; + char quote = '\0'; + int frenchBraces = 0, squareBraces = 0; + + for (len = 0; startAddr+len < endAddr; len++) { + if (!quote && !frenchBraces && !squareBraces && + *(startAddr+len) == ';') + break; + + switch (*(startAddr+len)) { + case '{': + frenchBraces++; + break; + case '}': + if (!frenchBraces) + fprintf(stderr, + "WARNING: found `}' without `{'.\n"); + else + frenchBraces--; + break; + case '[': + squareBraces++; + break; + case ']': + if (!squareBraces) + fprintf(stderr, + "WARNING: found ']' without '['.\n"); + else + squareBraces--; + break; + case '"': + if (!quote) + quote = *(startAddr+len); + else + quote = '\0'; + break; + } + } + + return len; +} + +-init +{ + return self; +} + +-free +{ + return [super free]; +} + +-(DataObject *) +getDataFrom: (String *)dataStr +{ + const char *dataBuff; + id dataElem; + + dataBuff = [dataStr getStr]; + + /* Figure out what type of node to allocate. */ + switch (dataBuff[0]) { + case '{': + dataElem = [[DictData new] init]; + break; + case '[': + dataElem = [[ArrayData new] init]; + break; + case '"': + dataElem = [[StringData new] init]; + break; + default: + dataElem = [[NumData new] init]; + break; + } + + return [dataElem setFromBuffer: dataBuff withLength: [dataStr getLen]]; +} +@end diff --git a/libconfig/String.h b/libconfig/String.h new file mode 100644 index 0000000..ab0aaad --- /dev/null +++ b/libconfig/String.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef STRING_H +# define STRING_H + +#include <Object.h> + +@interface String: Object +{ + char *data; + int len; +} + +-init; +-free; +-setStr: (const char *)stringData withLength: (int)length; +-setStr: (const char *)stringData; +-(int)getLen; +-(char *)getStr; +@end +#endif diff --git a/libconfig/String.m b/libconfig/String.m new file mode 100644 index 0000000..9a0bc5a --- /dev/null +++ b/libconfig/String.m @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "String.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +@implementation String +-init +{ + self = [super init]; + data = NULL; + return self; +} + +-free +{ + free(data); + return [super free]; +} + +-setStr: (const char *)stringData withLength: (int)length +{ + if (data) + free(data); + + data = malloc((length+1)*sizeof(char)); + if (!data) { + fprintf(stderr, "ERROR: Couldn't allocate memory: %s.\n", + strerror(errno)); + return nil; + } + + memcpy(data, stringData, length); + data[length] = '\0'; + len = length; + return self; +} + +-setStr: (const char *)stringData +{ + return [self setStr: stringData withLength: strlen(stringData)]; +} + +-(int) +getLen +{ + return len; +} + +-(char *) +getStr +{ + return data; +} +@end diff --git a/libconfig/StringData.h b/libconfig/StringData.h new file mode 100644 index 0000000..80c4d26 --- /dev/null +++ b/libconfig/StringData.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#ifndef STRINGDATA_H +# define STRINGDATA_H + +#include "Data.h" +#include "String.h" + +@interface StringData: DataObject +{ + String *data; +} + +-free; +@end +#endif diff --git a/libconfig/StringData.m b/libconfig/StringData.m new file mode 100644 index 0000000..1c02ac5 --- /dev/null +++ b/libconfig/StringData.m @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1998, Brian Cully <shmit@kublai.com> + * + * 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. The names of contributers to this software may not be used to endorse + * or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 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 REGENTS 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. + */ +#include "conf.h" + +#include "StringData.h" +#include "Parser.h" +#include "String.h" + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#if NEED_STRINGS +#include <strings.h> +#endif + +@implementation StringData +-init +{ + self = [super init]; + data = [[String new] init]; + return self; +} + +-free +{ + [data free]; + [super free]; + return self; +} + +-(char *) +createCStr +{ + char *buffer; + + buffer = malloc(([data getLen]+1) * sizeof(char)); + if (!buffer) { + fprintf(stderr, "ERROR: Couldn't allocate buffer: %s.\n", + strerror(errno)); + return NULL; + } + + strcpy(buffer, [data getStr]); + return buffer; +} + +-(String *) +createStr +{ + String *str; + char *buffer; + + buffer = [self createCStr]; + if (buffer == NULL) + return nil; + + str = [[[String new] init] setStr: buffer]; + free(buffer); + + return str; +} + +-setFromBuffer: (const char *)buffer withLength: (int)len +{ + const char *startPtr, *endPtr; + + startPtr = index(buffer, '"'); + if (!startPtr) { + fprintf(stderr, "ERROR: No opening quote for string.\n"); + return nil; + } + startPtr++; + + for (endPtr = buffer+len; endPtr > startPtr; endPtr--) + if (*endPtr == '"') + break; + + if (endPtr == startPtr) { + fprintf(stderr, "ERROR: No ending quote for string.\n"); + return nil; + } + endPtr--; + + [data setStr: startPtr withLength: endPtr-startPtr+1]; + return self; +} +@end diff --git a/libconfig/config.m b/libconfig/config.m new file mode 100644 index 0000000..b0d13a9 --- /dev/null +++ b/libconfig/config.m @@ -0,0 +1,287 @@ +#include "conf.h" +#include "config.h" +#include "nastipc.h" +#include "thread.h" + +#include "BuffIO.h" +#include "ArrayData.h" +#include "DictData.h" +#include "NumData.h" +#include "StringData.h" + +#include <netdb.h> +#include <stdlib.h> + +RCSID("$Id: config.m,v 1.5 2001/11/09 15:54:38 shmit Exp $"); + +/* + * Global variables. + */ +static DictData *root; +char config_filen[MAXPATHLEN]; +struct nast_config config; + +static int +config_read(const char *filename) +{ + BuffIO *confFile; + + confFile = [[[BuffIO new] init: filename] setEOL: ';']; + if (confFile == nil) { + fprintf(stderr, "ERROR: Couldn't load config file."); + return -1; + } + + root = [[DictData new] setFromBuffer: [confFile getCurOff] + withLength: [confFile getLength]]; + + /* We've duplicated all the data in here into private storage. */ + [confFile free]; + + if (root == nil) { + fprintf(stderr, "ERROR: Couldn't parse config file."); + return -1; + } + return 0; +} + +static int +get_val(const char *name, void *dst, enum data_type type) +{ + id node; + + node = [[root findChild: name] getData]; + if (node == nil) + return 0; + + switch (type) { + case NUMBER: + if (![node isKindOf: [NumData class]]) { + fprintf(stderr, "Node `%s' in `%s' should be a number.", + name, config_filen); + return -1; + } + *(int *)dst = [node getNum]; + break; + case STRING: + if (![node isKindOf: [StringData class]]) { + fprintf(stderr, "Node `%s' in `%s' should be a string.", + name, config_filen); + return -1; + } + *(char **)dst = [node createCStr]; + break; + case ARRAY: + fprintf(stderr, "ERROR: Can't load array into C yet."); + return -1; + case DICTIONARY: + fprintf(stderr, "ERROR: Can't load dictionary into C yet."); + return -1; + default: + fprintf(stderr, "ERROR: Don't know what to do with type `%d'.", + type); + return -1; + } + + return 0; +} + +/* + * Sets configuration variables to defaults, in case they're not set + * elsewhere. + */ +void +config_setdefaults() +{ + /* Set the defaults. */ + config.description = "Description not set in config file."; + config.nast_dir = DATADIR; + config.nast_sock = NASTHOLE; + config.nast_cdb_file = "nast.cdb"; + config.mysql_host = DBHOST; + config.mysql_user = DBUSER; + config.mysql_pass = DBPASS; + config.nofork_flag = 0; + config.null_cache_timeout = 60; + config.tcp_port = 31337; + + return; +} + +/* + * Initializes configuration variables from config file. + */ +int +config_init() +{ + snprintf(config_filen, sizeof(config_filen), + "%s/nastd.conf", config.nast_dir); + if (config_read(config_filen) == -1) + return -1; + + /* + * Now grab all the top-level config information. + */ + if (get_val("description", &config.description, STRING) == -1) + return -1; + + if (get_val("nast_dir", &config.nast_dir, STRING) == -1) + return -1; + + if (get_val("nast_sock", &config.nast_sock, STRING) == -1) + return -1; + + if (get_val("nast_cdb_file", &config.nast_cdb_file, STRING) == -1) + return -1; + + if (get_val("mysql_host", &config.mysql_host, STRING) == -1) + return -1; + + if (get_val("mysql_user", &config.mysql_user, STRING) == -1) + return -1; + + if (get_val("mysql_pass", &config.mysql_pass, STRING) == -1) + return -1; + + if (get_val("null_cache_timeout", &config.null_cache_timeout, + NUMBER) == -1) + return -1; + + if (get_val("tcp_port", &config.tcp_port, NUMBER) == -1) + return -1; + + return 0; +} + +void +config_delete() +{ + [root free]; +} + +static enum data_type +getctype(id node) +{ + if ([node isKindOf: [StringData class]]) + return STRING; + else if ([node isKindOf: [NumData class]]) + return NUMBER; + else if ([node isKindOf: [ArrayData class]]) + return ARRAY; + else if ([node isKindOf: [DictData class]]) + return DICTIONARY; + else { + return -1; + } +} + +void * +config_find(void *root_node, const char *name, enum data_type *type) +{ + id rootNode, dstNode; + + if (root_node == NULL) + root_node = root; + + rootNode = (id)root_node; + if ([rootNode isKindOf: [DictData class]] == NO) { + fprintf(stderr, "Trying to find `%s' in non-dictionary.", name); + return NULL; + } + + dstNode = [[rootNode findChild: name] getData]; + if (dstNode == nil) + return NULL; + *type = getctype(dstNode); + return dstNode; +} + +void * +config_arrayitemat(void *array, int index, enum data_type *type) +{ + id arrayNode, dstNode; + + if (array == NULL) + return NULL; + + arrayNode = (id)array; + if ([arrayNode isKindOf: [ArrayData class]] == NO) { + fprintf(stderr, "Trying to index in non-array."); + return NULL; + } + + if (index >= [arrayNode numObjects]) + return NULL; + + dstNode = [arrayNode objectAt: index]; + if (dstNode == nil) + return NULL; + *type = getctype(dstNode); + return dstNode; +} + +void * +config_dictitemat(void *dict, const char *name, enum data_type *type) +{ + id dictNode, dstNode; + + if (dict == NULL) + return NULL; + + dictNode = (id)dict; + if ([dictNode isKindOf: [DictData class]] == NO) { + fprintf(stderr, "Trying to find `%s' in non-dictionary.", name); + return NULL; + } + + dstNode = [[dictNode findChild: name] getData]; + if (dstNode == nil) + return NULL; + *type = getctype(dstNode); + return dstNode; +} + +void * +getdata(void *itemref, void *dst, enum data_type want_type) +{ + id item; + + if (itemref == NULL) + return NULL; + + item = (id)itemref; + if ([item isKindOf: [DataObject class]] == NO) { + fprintf(stderr, "Can only deref DataObject types " + "or sub-classes."); + return NULL; + } + + switch (want_type) { + case NUMBER: + if ([item isKindOf: [NumData class]] == NO) + return NULL; + *(int *)dst = [item getNum]; + break; + case STRING: + if ([item isKindOf: [StringData class]] == NO) + return NULL; + *(char **)dst = [item createCStr]; + break; + case ARRAY: + if ([item isKindOf: [ArrayData class]] == NO) + return NULL; + dst = [item getData]; + break; + case DICTIONARY: + if ([item isKindOf: [DictData class]] == NO) + return NULL; + dst = [item getData]; + break; + default: + fprintf(stderr, + "Can't deref type `%d': unknown type.", want_type); + return NULL; + } + + return dst; +} diff --git a/perl/.cvsignore b/perl/.cvsignore new file mode 100644 index 0000000..9809bfd --- /dev/null +++ b/perl/.cvsignore @@ -0,0 +1,6 @@ +Makefile +xstmp.c +pm_to_blib +blib +NASTD.bs +NASTD.c diff --git a/perl/.svn/README.txt b/perl/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/perl/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/perl/.svn/empty-file b/perl/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/perl/.svn/empty-file diff --git a/perl/.svn/entries b/perl/.svn/entries new file mode 100644 index 0000000..c7b6b8c --- /dev/null +++ b/perl/.svn/entries @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk/perl" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + committed-rev="1" + name="build" + text-time="2005-12-24T00:00:43.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="fa603e711052b12737e673725e56fab0" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:41.000000Z"/> +<entry + committed-rev="1" + name="typemap" + text-time="2005-12-24T00:00:43.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="56fdf9747cfbea1f792a7d8b44d39fe0" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:41.000000Z"/> +<entry + committed-rev="1" + name="NASTD.xs" + text-time="2005-12-24T00:00:43.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="0564b7827aae11422da8f56a84355ae3" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:42.000000Z"/> +<entry + name="include" + kind="dir"/> +<entry + committed-rev="1" + name="NASTD.pm" + text-time="2005-12-24T00:00:43.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="04fda49784b5602bae8b3d191b26bd01" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:42.000000Z"/> +<entry + committed-rev="1" + name="MANIFEST" + text-time="2005-12-24T00:00:44.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="c4cfc3f92bd63ddb8297973d577d46ac" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:42.000000Z"/> +<entry + committed-rev="1" + name="pm_to_blib" + text-time="2005-12-24T00:00:44.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="d41d8cd98f00b204e9800998ecf8427e" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:42.000000Z"/> +<entry + committed-rev="1" + name="Makefile.PL" + text-time="2005-12-24T00:00:44.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="594ed49aad05bff559e06ee540ed709d" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:42.000000Z"/> +<entry + committed-rev="1" + name="Changes" + text-time="2005-12-24T00:00:44.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="a98173ffb2742346ed8a881b97d813c3" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:43.000000Z"/> +<entry + committed-rev="1" + name="test.pl" + text-time="2005-12-24T00:00:44.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="ad0a9b680054139a9d6b8e7320367b0e" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:43.000000Z"/> +<entry + committed-rev="1" + name="Makefile.old" + text-time="2005-12-24T00:00:44.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="c41457a1f0b10e85c28160cfde15a816" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:43.000000Z"/> +<entry + committed-rev="1" + name=".cvsignore" + text-time="2005-12-24T00:00:44.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="0231912a31d56f4ab5d4a080b76c01ee" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:43.000000Z"/> +<entry + committed-rev="1" + name="test_fallthrough" + text-time="2005-12-24T00:00:44.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="2caba86618d54d5e84e2cee71c647825" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:43.000000Z"/> +</wc-entries> diff --git a/perl/.svn/format b/perl/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/perl/.svn/format @@ -0,0 +1 @@ +4 diff --git a/perl/.svn/prop-base/.cvsignore.svn-base b/perl/.svn/prop-base/.cvsignore.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/prop-base/.cvsignore.svn-base @@ -0,0 +1 @@ +END diff --git a/perl/.svn/prop-base/Changes.svn-base b/perl/.svn/prop-base/Changes.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/prop-base/Changes.svn-base @@ -0,0 +1 @@ +END diff --git a/perl/.svn/prop-base/MANIFEST.svn-base b/perl/.svn/prop-base/MANIFEST.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/prop-base/MANIFEST.svn-base @@ -0,0 +1 @@ +END diff --git a/perl/.svn/prop-base/Makefile.PL.svn-base b/perl/.svn/prop-base/Makefile.PL.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/prop-base/Makefile.PL.svn-base @@ -0,0 +1 @@ +END diff --git a/perl/.svn/prop-base/Makefile.old.svn-base b/perl/.svn/prop-base/Makefile.old.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/prop-base/Makefile.old.svn-base @@ -0,0 +1 @@ +END diff --git a/perl/.svn/prop-base/NASTD.pm.svn-base b/perl/.svn/prop-base/NASTD.pm.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/prop-base/NASTD.pm.svn-base @@ -0,0 +1 @@ +END diff --git a/perl/.svn/prop-base/NASTD.xs.svn-base b/perl/.svn/prop-base/NASTD.xs.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/prop-base/NASTD.xs.svn-base @@ -0,0 +1 @@ +END diff --git a/perl/.svn/prop-base/build.svn-base b/perl/.svn/prop-base/build.svn-base new file mode 100644 index 0000000..a669705 --- /dev/null +++ b/perl/.svn/prop-base/build.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 0 + +END diff --git a/perl/.svn/prop-base/pm_to_blib.svn-base b/perl/.svn/prop-base/pm_to_blib.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/prop-base/pm_to_blib.svn-base @@ -0,0 +1 @@ +END diff --git a/perl/.svn/prop-base/test.pl.svn-base b/perl/.svn/prop-base/test.pl.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/prop-base/test.pl.svn-base @@ -0,0 +1 @@ +END diff --git a/perl/.svn/prop-base/test_fallthrough.svn-base b/perl/.svn/prop-base/test_fallthrough.svn-base new file mode 100644 index 0000000..a669705 --- /dev/null +++ b/perl/.svn/prop-base/test_fallthrough.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 0 + +END diff --git a/perl/.svn/prop-base/typemap.svn-base b/perl/.svn/prop-base/typemap.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/prop-base/typemap.svn-base @@ -0,0 +1 @@ +END diff --git a/perl/.svn/props/.cvsignore.svn-work b/perl/.svn/props/.cvsignore.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/props/.cvsignore.svn-work @@ -0,0 +1 @@ +END diff --git a/perl/.svn/props/Changes.svn-work b/perl/.svn/props/Changes.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/props/Changes.svn-work @@ -0,0 +1 @@ +END diff --git a/perl/.svn/props/MANIFEST.svn-work b/perl/.svn/props/MANIFEST.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/props/MANIFEST.svn-work @@ -0,0 +1 @@ +END diff --git a/perl/.svn/props/Makefile.PL.svn-work b/perl/.svn/props/Makefile.PL.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/props/Makefile.PL.svn-work @@ -0,0 +1 @@ +END diff --git a/perl/.svn/props/Makefile.old.svn-work b/perl/.svn/props/Makefile.old.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/props/Makefile.old.svn-work @@ -0,0 +1 @@ +END diff --git a/perl/.svn/props/NASTD.pm.svn-work b/perl/.svn/props/NASTD.pm.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/props/NASTD.pm.svn-work @@ -0,0 +1 @@ +END diff --git a/perl/.svn/props/NASTD.xs.svn-work b/perl/.svn/props/NASTD.xs.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/props/NASTD.xs.svn-work @@ -0,0 +1 @@ +END diff --git a/perl/.svn/props/build.svn-work b/perl/.svn/props/build.svn-work new file mode 100644 index 0000000..a669705 --- /dev/null +++ b/perl/.svn/props/build.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 0 + +END diff --git a/perl/.svn/props/pm_to_blib.svn-work b/perl/.svn/props/pm_to_blib.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/props/pm_to_blib.svn-work @@ -0,0 +1 @@ +END diff --git a/perl/.svn/props/test.pl.svn-work b/perl/.svn/props/test.pl.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/props/test.pl.svn-work @@ -0,0 +1 @@ +END diff --git a/perl/.svn/props/test_fallthrough.svn-work b/perl/.svn/props/test_fallthrough.svn-work new file mode 100644 index 0000000..a669705 --- /dev/null +++ b/perl/.svn/props/test_fallthrough.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 0 + +END diff --git a/perl/.svn/props/typemap.svn-work b/perl/.svn/props/typemap.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/.svn/props/typemap.svn-work @@ -0,0 +1 @@ +END diff --git a/perl/.svn/text-base/.cvsignore.svn-base b/perl/.svn/text-base/.cvsignore.svn-base new file mode 100644 index 0000000..9809bfd --- /dev/null +++ b/perl/.svn/text-base/.cvsignore.svn-base @@ -0,0 +1,6 @@ +Makefile +xstmp.c +pm_to_blib +blib +NASTD.bs +NASTD.c diff --git a/perl/.svn/text-base/Changes.svn-base b/perl/.svn/text-base/Changes.svn-base new file mode 100644 index 0000000..5158653 --- /dev/null +++ b/perl/.svn/text-base/Changes.svn-base @@ -0,0 +1,5 @@ +Revision history for Perl extension ASSD. + +0.01 Thu May 11 16:58:38 2000 + - original version; created by h2xs 1.19 + diff --git a/perl/.svn/text-base/MANIFEST.svn-base b/perl/.svn/text-base/MANIFEST.svn-base new file mode 100644 index 0000000..1bd95ce --- /dev/null +++ b/perl/.svn/text-base/MANIFEST.svn-base @@ -0,0 +1,6 @@ +NASTD.pm +NASTD.xs +Changes +MANIFEST +Makefile.PL +test.pl diff --git a/perl/.svn/text-base/Makefile.PL.svn-base b/perl/.svn/text-base/Makefile.PL.svn-base new file mode 100644 index 0000000..a6d8f02 --- /dev/null +++ b/perl/.svn/text-base/Makefile.PL.svn-base @@ -0,0 +1,11 @@ +use ExtUtils::MakeMaker; +# See lib/ExtUtils/MakeMaker.pm for details of how to influence +# the contents of the Makefile that is written. +WriteMakefile( + 'NAME' => 'NASTD', + 'VERSION_FROM' => 'NASTD.pm', # finds $VERSION + 'LIBS' => ['-L../client -lnast'], # e.g., '-lm' + 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING' + 'INC' => '', # e.g., '-I/usr/include/other' + 'depend' => {'NAST.xs' => '../client/libnast.a'} +); diff --git a/perl/.svn/text-base/Makefile.old.svn-base b/perl/.svn/text-base/Makefile.old.svn-base new file mode 100644 index 0000000..d764b63 --- /dev/null +++ b/perl/.svn/text-base/Makefile.old.svn-base @@ -0,0 +1,761 @@ +# This Makefile is for the NASTD extension to perl. +# +# It was generated automatically by MakeMaker version +# 5.4302 (Revision: 1.222) from the contents of +# Makefile.PL. Don't edit this file, edit Makefile.PL instead. +# +# ANY CHANGES MADE HERE WILL BE LOST! +# +# MakeMaker ARGV: () +# +# MakeMaker Parameters: + +# DEFINE => q[] +# INC => q[] +# LIBS => [q[-L../client -lnast]] +# NAME => q[NASTD] +# VERSION_FROM => q[NASTD.pm] +# depend => { NAST.xs=>q[../client/libnast.a] } + +# --- MakeMaker post_initialize section: + + +# --- MakeMaker const_config section: + +# These definitions are from config.sh (via /usr/local/lib/perl5/5.00503/sun4-solaris/Config.pm) + +# They may have been overridden via Makefile.PL or on the command line +AR = ar +CC = gcc -B/usr/ccs/bin/ +CCCDLFLAGS = -fPIC +CCDLFLAGS = +DLEXT = so +DLSRC = dl_dlopen.xs +LD = gcc -B/usr/ccs/bin/ +LDDLFLAGS = -G -L/usr/local/lib +LDFLAGS = -L/usr/local/lib +LIBC = /lib/libc.so +LIB_EXT = .a +OBJ_EXT = .o +OSNAME = solaris +OSVERS = 2.6 +RANLIB = : +SO = so +EXE_EXT = + + +# --- MakeMaker constants section: +AR_STATIC_ARGS = cr +NAME = NASTD +DISTNAME = NASTD +NAME_SYM = NASTD +VERSION = 0.01 +VERSION_SYM = 0_01 +XS_VERSION = 0.01 +INST_BIN = blib/bin +INST_EXE = blib/script +INST_LIB = blib/lib +INST_ARCHLIB = blib/arch +INST_SCRIPT = blib/script +PREFIX = /usr/local +INSTALLDIRS = site +INSTALLPRIVLIB = $(PREFIX)/lib/perl5/5.00503 +INSTALLARCHLIB = $(PREFIX)/lib/perl5/5.00503/sun4-solaris +INSTALLSITELIB = $(PREFIX)/lib/perl5/site_perl/5.005 +INSTALLSITEARCH = $(PREFIX)/lib/perl5/site_perl/5.005/sun4-solaris +INSTALLBIN = $(PREFIX)/bin +INSTALLSCRIPT = $(PREFIX)/bin +PERL_LIB = /usr/local/lib/perl5/5.00503 +PERL_ARCHLIB = /usr/local/lib/perl5/5.00503/sun4-solaris +SITELIBEXP = /usr/local/lib/perl5/site_perl/5.005 +SITEARCHEXP = /usr/local/lib/perl5/site_perl/5.005/sun4-solaris +LIBPERL_A = libperl.a +FIRST_MAKEFILE = Makefile +MAKE_APERL_FILE = Makefile.aperl +PERLMAINCC = $(CC) +PERL_INC = /usr/local/lib/perl5/5.00503/sun4-solaris/CORE +PERL = /opt/bin/perl +FULLPERL = /opt/bin/perl + +VERSION_MACRO = VERSION +DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\" +XS_VERSION_MACRO = XS_VERSION +XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\" + +MAKEMAKER = /usr/local/lib/perl5/5.00503/ExtUtils/MakeMaker.pm +MM_VERSION = 5.4302 + +# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle). +# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle) +# ROOTEXT = Directory part of FULLEXT with leading slash (eg /DBD) !!! Deprecated from MM 5.32 !!! +# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar) +# DLBASE = Basename part of dynamic library. May be just equal BASEEXT. +FULLEXT = NASTD +BASEEXT = NASTD +DLBASE = $(BASEEXT) +VERSION_FROM = NASTD.pm +INC = +DEFINE = +OBJECT = $(BASEEXT)$(OBJ_EXT) +LDFROM = $(OBJECT) +LINKTYPE = dynamic + +# Handy lists of source code files: +XS_FILES= NASTD.xs +C_FILES = NASTD.c +O_FILES = NASTD.o +H_FILES = +MAN1PODS = +MAN3PODS = NASTD.pm +INST_MAN1DIR = blib/man1 +INSTALLMAN1DIR = /usr/local/man/man1 +MAN1EXT = 1 +INST_MAN3DIR = blib/man3 +INSTALLMAN3DIR = /usr/local/lib/perl5/5.00503/man/man3 +MAN3EXT = 3 +PERM_RW = 644 +PERM_RWX = 755 + +# work around a famous dec-osf make(1) feature(?): +makemakerdflt: all + +.SUFFIXES: .xs .c .C .cpp .cxx .cc $(OBJ_EXT) + +# Nick wanted to get rid of .PRECIOUS. I don't remember why. I seem to recall, that +# some make implementations will delete the Makefile when we rebuild it. Because +# we call false(1) when we rebuild it. So make(1) is not completely wrong when it +# does so. Our milage may vary. +# .PRECIOUS: Makefile # seems to be not necessary anymore + +.PHONY: all config static dynamic test linkext manifest + +# Where is the Config information that we are using/depend on +CONFIGDEP = $(PERL_ARCHLIB)/Config.pm $(PERL_INC)/config.h + +# Where to put things: +INST_LIBDIR = $(INST_LIB) +INST_ARCHLIBDIR = $(INST_ARCHLIB) + +INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT) +INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT) + +INST_STATIC = $(INST_ARCHAUTODIR)/$(BASEEXT)$(LIB_EXT) +INST_DYNAMIC = $(INST_ARCHAUTODIR)/$(DLBASE).$(DLEXT) +INST_BOOT = $(INST_ARCHAUTODIR)/$(BASEEXT).bs + +EXPORT_LIST = + +PERL_ARCHIVE = + +TO_INST_PM = NASTD.pm + +PM_TO_BLIB = NASTD.pm \ + $(INST_LIBDIR)/NASTD.pm + + +# --- MakeMaker tool_autosplit section: + +# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto +AUTOSPLITFILE = $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e 'use AutoSplit;autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1) ;' + + +# --- MakeMaker tool_xsubpp section: + +XSUBPPDIR = /usr/local/lib/perl5/5.00503/ExtUtils +XSUBPP = $(XSUBPPDIR)/xsubpp +XSPROTOARG = +XSUBPPDEPS = $(XSUBPPDIR)/typemap typemap +XSUBPPARGS = -typemap $(XSUBPPDIR)/typemap -typemap typemap + + +# --- MakeMaker tools_other section: + +SHELL = /bin/sh +CHMOD = chmod +CP = cp +LD = gcc -B/usr/ccs/bin/ +MV = mv +NOOP = $(SHELL) -c true +RM_F = rm -f +RM_RF = rm -rf +TEST_F = test -f +TOUCH = touch +UMASK_NULL = umask 0 +DEV_NULL = > /dev/null 2>&1 + +# The following is a portable way to say mkdir -p +# To see which directories are created, change the if 0 to if 1 +MKPATH = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e mkpath + +# This helps us to minimize the effect of the .exists files A yet +# better solution would be to have a stable file in the perl +# distribution with a timestamp of zero. But this solution doesn't +# need any changes to the core distribution and works with older perls +EQUALIZE_TIMESTAMP = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e eqtime + +# Here we warn users that an old packlist file was found somewhere, +# and that they should call some uninstall routine +WARN_IF_OLD_PACKLIST = $(PERL) -we 'exit unless -f $$ARGV[0];' \ +-e 'print "WARNING: I have found an old package in\n";' \ +-e 'print "\t$$ARGV[0].\n";' \ +-e 'print "Please make sure the two installations are not conflicting\n";' + +UNINST=0 +VERBINST=1 + +MOD_INSTALL = $(PERL) -I$(INST_LIB) -I$(PERL_LIB) -MExtUtils::Install \ +-e "install({@ARGV},'$(VERBINST)',0,'$(UNINST)');" + +DOC_INSTALL = $(PERL) -e '$$\="\n\n";' \ +-e 'print "=head2 ", scalar(localtime), ": C<", shift, ">", " L<", shift, ">";' \ +-e 'print "=over 4";' \ +-e 'while (defined($$key = shift) and defined($$val = shift)){print "=item *";print "C<$$key: $$val>";}' \ +-e 'print "=back";' + +UNINSTALL = $(PERL) -MExtUtils::Install \ +-e 'uninstall($$ARGV[0],1,1); print "\nUninstall is deprecated. Please check the";' \ +-e 'print " packlist above carefully.\n There may be errors. Remove the";' \ +-e 'print " appropriate files manually.\n Sorry for the inconveniences.\n"' + + +# --- MakeMaker dist section: + +DISTVNAME = $(DISTNAME)-$(VERSION) +TAR = tar +TARFLAGS = cvf +ZIP = zip +ZIPFLAGS = -r +COMPRESS = gzip --best +SUFFIX = .gz +SHAR = shar +PREOP = @$(NOOP) +POSTOP = @$(NOOP) +TO_UNIX = @$(NOOP) +CI = ci -u +RCS_LABEL = rcs -Nv$(VERSION_SYM): -q +DIST_CP = best +DIST_DEFAULT = tardist + + +# --- MakeMaker macro section: + + +# --- MakeMaker depend section: +NAST.xs: ../client/libnast.a + + +# --- MakeMaker cflags section: + +CCFLAGS = -O2 -pipe -I/usr/local/include +OPTIMIZE = -O +PERLTYPE = +LARGE = +SPLIT = + + +# --- MakeMaker const_loadlibs section: + +# NASTD might depend on some other libraries: +# See ExtUtils::Liblist for details +# +EXTRALIBS = -L/usr/home/shmit/src/nastd/perl/../client -lnast +LDLOADLIBS = -L/usr/home/shmit/src/nastd/perl/../client -lnast +BSLOADLIBS = +LD_RUN_PATH = /usr/home/shmit/src/nastd/perl/../client + + +# --- MakeMaker const_cccmd section: +CCCMD = $(CC) -c $(INC) $(CCFLAGS) $(OPTIMIZE) \ + $(PERLTYPE) $(LARGE) $(SPLIT) $(DEFINE_VERSION) \ + $(XS_DEFINE_VERSION) + +# --- MakeMaker post_constants section: + + +# --- MakeMaker pasthru section: + +PASTHRU = LIB="$(LIB)"\ + LIBPERL_A="$(LIBPERL_A)"\ + LINKTYPE="$(LINKTYPE)"\ + PREFIX="$(PREFIX)"\ + OPTIMIZE="$(OPTIMIZE)" + + +# --- MakeMaker c_o section: + +.c$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.c + +.C$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.C + +.cpp$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.cpp + +.cxx$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.cxx + +.cc$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.cc + + +# --- MakeMaker xs_c section: + +.xs.c: + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $*.xs >xstmp.c && $(MV) xstmp.c $*.c + + +# --- MakeMaker xs_o section: + +.xs$(OBJ_EXT): + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $*.xs >xstmp.c && $(MV) xstmp.c $*.c + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.c + + +# --- MakeMaker top_targets section: + +#all :: config $(INST_PM) subdirs linkext manifypods + +all :: pure_all manifypods + @$(NOOP) + +pure_all :: config pm_to_blib subdirs linkext + @$(NOOP) + +subdirs :: $(MYEXTLIB) + @$(NOOP) + +config :: Makefile $(INST_LIBDIR)/.exists + @$(NOOP) + +config :: $(INST_ARCHAUTODIR)/.exists + @$(NOOP) + +config :: $(INST_AUTODIR)/.exists + @$(NOOP) + +config :: Version_check + @$(NOOP) + + +$(INST_AUTODIR)/.exists :: /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h + @$(MKPATH) $(INST_AUTODIR) + @$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h $(INST_AUTODIR)/.exists + + -@$(CHMOD) $(PERM_RWX) $(INST_AUTODIR) + +$(INST_LIBDIR)/.exists :: /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h + @$(MKPATH) $(INST_LIBDIR) + @$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h $(INST_LIBDIR)/.exists + + -@$(CHMOD) $(PERM_RWX) $(INST_LIBDIR) + +$(INST_ARCHAUTODIR)/.exists :: /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h + @$(MKPATH) $(INST_ARCHAUTODIR) + @$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h $(INST_ARCHAUTODIR)/.exists + + -@$(CHMOD) $(PERM_RWX) $(INST_ARCHAUTODIR) + +config :: $(INST_MAN3DIR)/.exists + @$(NOOP) + + +$(INST_MAN3DIR)/.exists :: /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h + @$(MKPATH) $(INST_MAN3DIR) + @$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h $(INST_MAN3DIR)/.exists + + -@$(CHMOD) $(PERM_RWX) $(INST_MAN3DIR) + +help: + perldoc ExtUtils::MakeMaker + +Version_check: + @$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) \ + -MExtUtils::MakeMaker=Version_check \ + -e "Version_check('$(MM_VERSION)')" + + +# --- MakeMaker linkext section: + +linkext :: $(LINKTYPE) + @$(NOOP) + + +# --- MakeMaker dlsyms section: + + +# --- MakeMaker dynamic section: + +## $(INST_PM) has been moved to the all: target. +## It remains here for awhile to allow for old usage: "make dynamic" +#dynamic :: Makefile $(INST_DYNAMIC) $(INST_BOOT) $(INST_PM) +dynamic :: Makefile $(INST_DYNAMIC) $(INST_BOOT) + @$(NOOP) + + +# --- MakeMaker dynamic_bs section: + +BOOTSTRAP = NASTD.bs + +# As Mkbootstrap might not write a file (if none is required) +# we use touch to prevent make continually trying to remake it. +# The DynaLoader only reads a non-empty file. +$(BOOTSTRAP): Makefile $(INST_ARCHAUTODIR)/.exists + @echo "Running Mkbootstrap for $(NAME) ($(BSLOADLIBS))" + @$(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" \ + -MExtUtils::Mkbootstrap \ + -e "Mkbootstrap('$(BASEEXT)','$(BSLOADLIBS)');" + @$(TOUCH) $(BOOTSTRAP) + $(CHMOD) $(PERM_RW) $@ + +$(INST_BOOT): $(BOOTSTRAP) $(INST_ARCHAUTODIR)/.exists + @rm -rf $(INST_BOOT) + -cp $(BOOTSTRAP) $(INST_BOOT) + $(CHMOD) $(PERM_RW) $@ + + +# --- MakeMaker dynamic_lib section: + +# This section creates the dynamically loadable $(INST_DYNAMIC) +# from $(OBJECT) and possibly $(MYEXTLIB). +ARMAYBE = : +OTHERLDFLAGS = +INST_DYNAMIC_DEP = + +$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)/.exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP) + LD_RUN_PATH="$(LD_RUN_PATH)" $(LD) -o $@ -R/usr/home/shmit/src/nastd/perl/../client $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) $(EXPORT_LIST) + $(CHMOD) $(PERM_RWX) $@ + + +# --- MakeMaker static section: + +## $(INST_PM) has been moved to the all: target. +## It remains here for awhile to allow for old usage: "make static" +#static :: Makefile $(INST_STATIC) $(INST_PM) +static :: Makefile $(INST_STATIC) + @$(NOOP) + + +# --- MakeMaker static_lib section: + +$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)/.exists + $(RM_RF) $@ + $(AR) $(AR_STATIC_ARGS) $@ $(OBJECT) && $(RANLIB) $@ + $(CHMOD) $(PERM_RWX) $@ + @echo "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)/extralibs.ld + + + +# --- MakeMaker manifypods section: +POD2MAN_EXE = /usr/local/bin/pod2man +POD2MAN = $(PERL) -we '%m=@ARGV;for (keys %m){' \ +-e 'next if -e $$m{$$_} && -M $$m{$$_} < -M $$_ && -M $$m{$$_} < -M "Makefile";' \ +-e 'print "Manifying $$m{$$_}\n";' \ +-e 'system(qq[$$^X ].q["-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" $(POD2MAN_EXE) ].qq[$$_>$$m{$$_}])==0 or warn "Couldn\047t install $$m{$$_}\n";' \ +-e 'chmod(oct($(PERM_RW))), $$m{$$_} or warn "chmod $(PERM_RW) $$m{$$_}: $$!\n";}' + +manifypods : pure_all NASTD.pm + @$(POD2MAN) \ + NASTD.pm \ + $(INST_MAN3DIR)/NASTD.$(MAN3EXT) + +# --- MakeMaker processPL section: + + +# --- MakeMaker installbin section: + + +# --- MakeMaker subdirs section: + +# none + +# --- MakeMaker clean section: + +# Delete temporary files but do not touch installed files. We don't delete +# the Makefile here so a later make realclean still has a makefile to use. + +clean :: + -rm -rf NASTD.c ./blib $(MAKE_APERL_FILE) $(INST_ARCHAUTODIR)/extralibs.all perlmain.c mon.out core so_locations pm_to_blib *~ */*~ */*/*~ *$(OBJ_EXT) *$(LIB_EXT) perl.exe $(BOOTSTRAP) $(BASEEXT).bso $(BASEEXT).def $(BASEEXT).exp + -mv Makefile Makefile.old $(DEV_NULL) + + +# --- MakeMaker realclean section: + +# Delete temporary files (via clean) and also delete installed files +realclean purge :: clean + rm -rf $(INST_AUTODIR) $(INST_ARCHAUTODIR) + rm -f $(INST_DYNAMIC) $(INST_BOOT) + rm -f $(INST_STATIC) + rm -f $(INST_LIBDIR)/NASTD.pm + rm -rf Makefile Makefile.old + + +# --- MakeMaker dist_basics section: + +distclean :: realclean distcheck + +distcheck : + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=fullcheck \ + -e fullcheck + +skipcheck : + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=skipcheck \ + -e skipcheck + +manifest : + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=mkmanifest \ + -e mkmanifest + + +# --- MakeMaker dist_core section: + +dist : $(DIST_DEFAULT) + @$(PERL) -le 'print "Warning: Makefile possibly out of date with $$vf" if ' \ + -e '-e ($$vf="$(VERSION_FROM)") and -M $$vf < -M "Makefile";' + +tardist : $(DISTVNAME).tar$(SUFFIX) + +zipdist : $(DISTVNAME).zip + +$(DISTVNAME).tar$(SUFFIX) : distdir + $(PREOP) + $(TO_UNIX) + $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(COMPRESS) $(DISTVNAME).tar + $(POSTOP) + +$(DISTVNAME).zip : distdir + $(PREOP) + $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(POSTOP) + +uutardist : $(DISTVNAME).tar$(SUFFIX) + uuencode $(DISTVNAME).tar$(SUFFIX) \ + $(DISTVNAME).tar$(SUFFIX) > \ + $(DISTVNAME).tar$(SUFFIX)_uu + +shdist : distdir + $(PREOP) + $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar + $(RM_RF) $(DISTVNAME) + $(POSTOP) + + +# --- MakeMaker dist_dir section: + +distdir : + $(RM_RF) $(DISTVNAME) + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=manicopy,maniread \ + -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');" + + +# --- MakeMaker dist_test section: + +disttest : distdir + cd $(DISTVNAME) && $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) Makefile.PL + cd $(DISTVNAME) && $(MAKE) + cd $(DISTVNAME) && $(MAKE) test + + +# --- MakeMaker dist_ci section: + +ci : + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=maniread \ + -e "@all = keys %{ maniread() };" \ + -e 'print("Executing $(CI) @all\n"); system("$(CI) @all");' \ + -e 'print("Executing $(RCS_LABEL) ...\n"); system("$(RCS_LABEL) @all");' + + +# --- MakeMaker install section: + +install :: all pure_install doc_install + +install_perl :: all pure_perl_install doc_perl_install + +install_site :: all pure_site_install doc_site_install + +install_ :: install_site + @echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +pure_install :: pure_$(INSTALLDIRS)_install + +doc_install :: doc_$(INSTALLDIRS)_install + @echo Appending installation info to $(INSTALLARCHLIB)/perllocal.pod + +pure__install : pure_site_install + @echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +doc__install : doc_site_install + @echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +pure_perl_install :: + @$(MOD_INSTALL) \ + read $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist \ + write $(INSTALLARCHLIB)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(INSTALLPRIVLIB) \ + $(INST_ARCHLIB) $(INSTALLARCHLIB) \ + $(INST_BIN) $(INSTALLBIN) \ + $(INST_SCRIPT) $(INSTALLSCRIPT) \ + $(INST_MAN1DIR) $(INSTALLMAN1DIR) \ + $(INST_MAN3DIR) $(INSTALLMAN3DIR) + @$(WARN_IF_OLD_PACKLIST) \ + $(SITEARCHEXP)/auto/$(FULLEXT) + + +pure_site_install :: + @$(MOD_INSTALL) \ + read $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist \ + write $(INSTALLSITEARCH)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(INSTALLSITELIB) \ + $(INST_ARCHLIB) $(INSTALLSITEARCH) \ + $(INST_BIN) $(INSTALLBIN) \ + $(INST_SCRIPT) $(INSTALLSCRIPT) \ + $(INST_MAN1DIR) $(INSTALLMAN1DIR) \ + $(INST_MAN3DIR) $(INSTALLMAN3DIR) + @$(WARN_IF_OLD_PACKLIST) \ + $(PERL_ARCHLIB)/auto/$(FULLEXT) + +doc_perl_install :: + -@$(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLPRIVLIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(INSTALLARCHLIB)/perllocal.pod + +doc_site_install :: + -@$(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLSITELIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(INSTALLARCHLIB)/perllocal.pod + + +uninstall :: uninstall_from_$(INSTALLDIRS)dirs + +uninstall_from_perldirs :: + @$(UNINSTALL) $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist + +uninstall_from_sitedirs :: + @$(UNINSTALL) $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist + + +# --- MakeMaker force section: +# Phony target to force checking subdirectories. +FORCE: + @$(NOOP) + + +# --- MakeMaker perldepend section: + +PERL_HDRS = \ +$(PERL_INC)/EXTERN.h $(PERL_INC)/gv.h $(PERL_INC)/pp.h \ +$(PERL_INC)/INTERN.h $(PERL_INC)/handy.h $(PERL_INC)/proto.h \ +$(PERL_INC)/XSUB.h $(PERL_INC)/hv.h $(PERL_INC)/regcomp.h \ +$(PERL_INC)/av.h $(PERL_INC)/keywords.h $(PERL_INC)/regexp.h \ +$(PERL_INC)/config.h $(PERL_INC)/mg.h $(PERL_INC)/scope.h \ +$(PERL_INC)/cop.h $(PERL_INC)/op.h $(PERL_INC)/sv.h \ +$(PERL_INC)/cv.h $(PERL_INC)/opcode.h $(PERL_INC)/unixish.h \ +$(PERL_INC)/dosish.h $(PERL_INC)/patchlevel.h $(PERL_INC)/util.h \ +$(PERL_INC)/embed.h $(PERL_INC)/perl.h $(PERL_INC)/iperlsys.h \ +$(PERL_INC)/form.h $(PERL_INC)/perly.h + +$(OBJECT) : $(PERL_HDRS) + +NASTD.c : $(XSUBPPDEPS) + + +# --- MakeMaker makefile section: + +$(OBJECT) : $(FIRST_MAKEFILE) + +# We take a very conservative approach here, but it\'s worth it. +# We move Makefile to Makefile.old here to avoid gnu make looping. +Makefile : Makefile.PL $(CONFIGDEP) + @echo "Makefile out-of-date with respect to $?" + @echo "Cleaning current config before rebuilding Makefile..." + -@$(RM_F) Makefile.old + -@$(MV) Makefile Makefile.old + -$(MAKE) -f Makefile.old clean $(DEV_NULL) || $(NOOP) + $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" Makefile.PL + @echo "==> Your Makefile has been rebuilt. <==" + @echo "==> Please rerun the make command. <==" + false + +# To change behavior to :: would be nice, but would break Tk b9.02 +# so you find such a warning below the dist target. +#Makefile :: $(VERSION_FROM) +# @echo "Warning: Makefile possibly out of date with $(VERSION_FROM)" + + +# --- MakeMaker staticmake section: + +# --- MakeMaker makeaperl section --- +MAP_TARGET = perl +FULLPERL = /opt/bin/perl + +$(MAP_TARGET) :: static $(MAKE_APERL_FILE) + $(MAKE) -f $(MAKE_APERL_FILE) $@ + +$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) + @echo Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) + @$(PERL) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) \ + Makefile.PL DIR= \ + MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ + MAKEAPERL=1 NORECURS=1 CCCDLFLAGS= + + +# --- MakeMaker test section: + +TEST_VERBOSE=0 +TEST_TYPE=test_$(LINKTYPE) +TEST_FILE = test.pl +TEST_FILES = +TESTDB_SW = -d + +testdb :: testdb_$(LINKTYPE) + +test :: $(TEST_TYPE) + +test_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERL) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(TEST_FILE) + +testdb_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERL) $(TESTDB_SW) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(TEST_FILE) + +test_ : test_dynamic + +test_static :: pure_all $(MAP_TARGET) + PERL_DL_NONLAZY=1 ./$(MAP_TARGET) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(TEST_FILE) + +testdb_static :: pure_all $(MAP_TARGET) + PERL_DL_NONLAZY=1 ./$(MAP_TARGET) $(TESTDB_SW) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(TEST_FILE) + + + +# --- MakeMaker ppd section: +# Creates a PPD (Perl Package Description) for a binary distribution. +ppd: + @$(PERL) -e "print qq{<SOFTPKG NAME=\"NASTD\" VERSION=\"0,01,0,0\">\n}. qq{\t<TITLE>NASTD</TITLE>\n}. qq{\t<ABSTRACT></ABSTRACT>\n}. qq{\t<AUTHOR></AUTHOR>\n}. qq{\t<IMPLEMENTATION>\n}. qq{\t\t<OS NAME=\"$(OSNAME)\" />\n}. qq{\t\t<ARCHITECTURE NAME=\"sun4-solaris\" />\n}. qq{\t\t<CODEBASE HREF=\"\" />\n}. qq{\t</IMPLEMENTATION>\n}. qq{</SOFTPKG>\n}" > NASTD.ppd + +# --- MakeMaker pm_to_blib section: + +pm_to_blib: $(TO_INST_PM) + @$(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" \ + "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -MExtUtils::Install \ + -e "pm_to_blib({qw{$(PM_TO_BLIB)}},'$(INST_LIB)/auto')" + @$(TOUCH) $@ + + +# --- MakeMaker selfdocument section: + + +# --- MakeMaker postamble section: + + +# End. diff --git a/perl/.svn/text-base/NASTD.pm.svn-base b/perl/.svn/text-base/NASTD.pm.svn-base new file mode 100644 index 0000000..70be2ff --- /dev/null +++ b/perl/.svn/text-base/NASTD.pm.svn-base @@ -0,0 +1,313 @@ +# $Id: NASTD.pm,v 1.7 2001/10/29 11:18:20 shmit Exp $ + +package NASTD; + +use strict; +use Carp; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD); + +require Exporter; +require DynaLoader; +require AutoLoader; + +@ISA = qw(Exporter DynaLoader); +# Items to export into callers namespace by default. Note: do not export +# names by default without a very good reason. Use EXPORT_OK instead. +# Do not simply export all your public functions/methods/constants. +@EXPORT = qw( + NAST_OK + NAST_SERVER_GONE + NAST_NOMEM + NAST_UNKNOWN_RESPONSE + NAST_TIMEDOUT + NAST_UNKNOWN_OPT + NAST_SERVER_ERR +); +$VERSION = '0.01'; + +sub AUTOLOAD { + # This AUTOLOAD is used to 'autoload' constants from the constant() + # XS function. If a constant is not found then control is passed + # to the AUTOLOAD in AutoLoader. + + my $constname; + ($constname = $AUTOLOAD) =~ s/.*:://; + croak "& not defined" if $constname eq 'constant'; + my $val = constant($constname, @_ ? $_[0] : 0); + if ($! != 0) { + if ($! =~ /Invalid/) { + $AutoLoader::AUTOLOAD = $AUTOLOAD; + goto &AutoLoader::AUTOLOAD; + } + else { + croak "Your vendor has not defined NASTD macro $constname"; + } + } + no strict 'refs'; + *$AUTOLOAD = sub () { $val }; + goto &$AUTOLOAD; +} + +bootstrap NASTD $VERSION; + +# Preloaded methods go here. + +# Autoload methods go after =cut, and are processed by the autosplit program. + +1; +__END__ +# Below is the stub of documentation for your module. You better edit it! + +=head1 NAME + +NASTD - Low level Perl extension for NASTD access methods + +=head1 SYNOPSIS + + use NASTD; + + $nasthole = &NASTD::nast_sphincter_new(); + &NASTD::nast_sphincter_close($nasthole); + + $rv = &NASTD::nast_options_get($nasthole); + $rv = &NASTD::nast_options_set($nasthole, @options); + + @values = &NASTD::nast_get_result($nasthole); + + $rv = &NASTD::nast_add($sphincter, $key); + $rv = &NASTD::nast_del($sphincter, $key); + $rv = &NASTD::nast_get($sphincter, $key); + $rv = &NASTD::nast_upd($sphincter, $key, $values); + + $rv = &NASTD::nast_stats($sphincter); + + $errcode = &NASTD::nast_geterr($sphincter); + $errstring = &NASTD::nast_errmsg($sphincter); + +=head1 DESCRIPTION + +The Perl NASTD module allows access to the NASTD server via a Perl +interface. It allows you to do anything you could do through C, such as +get records, update records, or delete records. It also allows setting +of various NASTD connection options, as you would through C. + +=head2 Opening a sphincter + +To do any work with NASTD at all, you must first open a sphincter, +through which you talk to your NASNASTole. This is fairly +straightforward: just call C<nast_sphincter_new()> and save the +returned handle. When you're done with the connection to your NAST, call +C<nast_sphincter_close()> to terminate it and free all memory of it. + +You may specify an optional argument, which points to the unix domain +socket name that you wish to use. By default, this is set to +"/tmp/nastd.sock". + +When an error occurs in C<nast_sphincter_new()>, you cannot call +C<nast_geterr()> since there's no sphincter with which to call it. +Instead, an error message will be printed on B<STDERR> for you to +diagnose, and the return value will be undefined. + +=head2 Checking errors + +There are many places during an NASTD session that errors can be +generated. To check for the presense of an error, call C<nast_geterr()> +with the sphincter returned from C<nast_sphincter_new()>. This will +return an error code, which is defined below under B<CONSTANTS>. + +If you would rather a printable string be returned, you can call +C<nast_errmsg()> with an open sphincter, and a printable string will be +returned. + +=head2 Performing a query + +Once you have an open sphincter, obtained via C<nast_sphincter_new()>, +you can start to query it with C<nast_add()>, C<nast_del()>, +C<nast_get()>, and C<nast_upd()>. + +The B<$key> is just that, a case-sensitive key for the database you're +querying. It's function depends on which query function you're using: + + Function Key Meaning + -------- ----------- + nast_add() Add this key to NASTD, with default values. + nast_del() Delete this key from NASTD. + nast_get() Return values associated with this key. + nast_upd() Update this key in NASTD with my values. + +All four of these functions return a status. If everything went okay, +then 0 is returned, otherwise -1 is returned, and you should check for +an error with C<nast_geterr()>. + +In the case of C<nast_add()>, C<nast_del()>, and C<nast_upd()> all you +need to do is call the query function and check for errors. If there +are no errors, then everything went fine. + +However, in the case of C<nast_get()>, you probably want the values +nastociated with the query you made. To get these values, you have to +call C<nast_get_result()>, which returns an array of values. + +=head2 Updating the database via C<nast_upd()> + +C<nast_upd()> works like the other query functions, except that in +addition to the key, you also need to pass an array of values. The +array needs to have the same number of elements as the NASTD database +has, and the elements should be in the same order as that specified in +the special key, "B<_VALUES_>" (see B<Key concepts and values>, +below). + +If the key you are trying to update does not exist, the server creates +it and gives it the values you specified in your value array. For this +reason C<nast_upd()> is preferable to C<nast_add()>. In fact, +C<nast_add()> may not exist very much longer. + +=head2 Key concepts and values + +It is recommended that before you try to do any real work with a +particular NASTD suppository, you first investigate the contents of the +special keys B<_KEY_> and B<_VALUES_>. You can do a regular query on +them using C<nast_get($nasthole, "_VALUES_")> followed by +C<nast_get_result()> to investigate their columns. + + Special Key Value Meaning + ----------- ------------- + _KEY_ The type of key the database is keyed on, + e.g., "username" would mean this database + is a username -> _VALUES_ mapping. + _VALUES_ The data being stored for every key in + the database. The order here is important, + as it's the same order that you'll get + when calling nast_get_result(). + _DELIM_ Only used internally to the NASTD server. + +As noted above, the B<_VALUES_> key shows what data you can find in the +NASTD database, as well as the order it is returned in. This is why you +should investigate this key before trying to do any real work with +NASTD. You have to know what columns mean what values for any real +decision making to be done. + +=head2 Server options + +In order to fine-tune server performance and behaviour, it is possible +to set various server-side options through the C<nast_options_get()> and +C<nast_options_set()> APIs. + +The interface is a bit clumsy at the low level - you pass in an array +to C<nast_options_set()> which has the options in a specific order, and +you get an array back from C<nast_options_get()> which contains the +options in a specific order. + +It is recommended that before you call C<nast_options_set()> that you +first obtain the default options from the server through +C<nast_options_get()> and manipulate the values you care about. Then +pass that array back to C<nast_options_set()>. + +The options you can set are as follows (remember to keep this order!): + + Index C Option Name Meaning (type) + ----- ------------- -------------- + 0 use_qcache Whether or not to use the + in-memory query cache. (BOOL) + 1 use_localdb Whether or not to use the on-disk + database. (BOOL) + 2 fallthrough_async Whether or not to use an + asynchronous API for fallthrough + queries. (BOOL) + 3 always_fallthrough Whether or not to always check + the fallthrough cache over the + local ones. Setting this to 1 + is the same as setting use_qcache + and use_localdb to 0. (BOOL) + 4 fail_once Whether or not to check a query + in the local and in-memory storage + once, and fail if the result isn't + found the first time, then defer + the next query to the fallthrough + queue. (BOOL) + 5 no_fallthrough Disable fallthrough queriers to + MySQL server. (BOOL) + +=head1 STATISTICS + +The C<nast_stats()> function is used to gather server statistics. First +you call C<nast_stats()>, which grabs the statistics and stores them as +a result. Then you call C<nast_getresult()> as you would for a query. + +The statistics come back in a human readable array, suitable for printing. + +=head1 CONSTANTS + +The only constants returned are via C<nast_geterr()>: + + Error Code Meaning + ---------- ------- + NAST_OK No errors occured. + NAST_SERVER_GONE The connection to the server no longer + exists. + NAST_NOMEM The client has run out of memory performing + an operation. + NAST_UNKNOWN_RESPONSE The server sent us a response we can't + understand. + NAST_TIMEDOUT The soft timeout on a query has elapsed. + This normally means the server is a bit + bogged down, and the query should be + retried. + NAST_UNKNOWN_OPT The server sent us an unknown option or + we tried to set an unknown option. + NAST_SERVER_ERR Generic server side error. Check + nast_errmsg() for more details. + +=head1 SAMPLE PROGRAM + + #!/usr/bin/env perl + + use NASTD; + + $nasthole = &NASTD::nast_sphincter_new(); + if (!defined($nasthole)) { + # Error message already printed. + exit(1); + } + + # Don't fallthrough to MySQL for this query. + # First we get the default options from the server, then tweak + # the ones we care about, and update the server with our options. + @options = &NASTD::nast_options_get($nasthole); + if (!defined(@options)) { + print STDERR "Couldn't get options: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + } + $options[5] = 1; + + if (&NASTD::nast_options_set($nasthole, @options) == -1) { + print STDERR "Couldn't set options: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + } + + # Get some values. + if (&NASTD::nast_get($nasthole, "shmit") == -1) { + print STDERR "Couldn't perform get: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + &NASTD::nast_close_sphincter($nasthole); + exit(1); + } + + @vals = &NASTD::nast_get_result($nasthole); + $nitems = $#vals + 1; + print "Number of columns: $nitems.\n"; + for ($i = 0; $i < $nitems; $i++) { + $val = shift(@vals); + print "Result[$i]: $val\n"; + } + + &NASTD::nast_sphincter_close($nasthole); + +=head1 BUGS + +fail_once behaviour is not working as of this writing. + +=head1 AUTHOR + +Brian Cully <L<shmit@rcn.com|mailto:shmit@rcn.com>> + +=cut diff --git a/perl/.svn/text-base/NASTD.xs.svn-base b/perl/.svn/text-base/NASTD.xs.svn-base new file mode 100644 index 0000000..e7b1179 --- /dev/null +++ b/perl/.svn/text-base/NASTD.xs.svn-base @@ -0,0 +1,278 @@ +/* $Id: NASTD.xs,v 1.5 2001/10/29 11:18:20 shmit Exp $ */ + +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +#include "../include/nastd.h" + +#include "include/nastdxs.def" + +static int +not_here(char *s) +{ + croak("%s not implemented on this architecture", s); + return -1; +} + +static double +constant(char *name, int arg) +{ + errno = 0; + switch (*name) { + case 'A': + if (strEQ(name, "NAST_OK")) + return NAST_OK; + else if (strEQ(name, "NAST_SERVER_GONE")) + return NAST_SERVER_GONE; + else if (strEQ(name, "NAST_NOMEM")) + return NAST_NOMEM; + else if (strEQ(name, "NAST_UNNKNOWN_RESPONSE")) + return NAST_UNKNOWN_RESPONSE; + else if (strEQ(name, "NAST_TIMEDOUT")) + return NAST_TIMEDOUT; + else if (strEQ(name, "NAST_UNKNOWN_OPT")) + return NAST_UNKNOWN_OPT; + else if (strEQ(name, "NAST_SERVER_ERR")) + return NAST_SERVER_ERR; + break; + case 'B': + break; + case 'C': + break; + case 'D': + break; + case 'E': + break; + case 'F': + break; + case 'G': + break; + case 'H': + break; + case 'I': + break; + case 'J': + break; + case 'K': + break; + case 'L': + break; + case 'M': + break; + case 'N': + break; + case 'O': + break; + case 'P': + break; + case 'Q': + break; + case 'R': + break; + case 'S': + break; + case 'T': + break; + case 'U': + break; + case 'V': + break; + case 'W': + break; + case 'X': + break; + case 'Y': + break; + case 'Z': + break; + } + errno = EINVAL; + return 0; + +not_there: + errno = ENOENT; + return 0; +} + + +MODULE = NASTD PACKAGE = NASTD + +PROTOTYPES: ENABLE + +double +constant(name,arg) + char * name + int arg + +nasth * +nast_sphincter_new(...) + PREINIT: + STRLEN n_a; + + CODE: + nasth *sphincter; + + if (items == 0) + sphincter = nast_sphincter_new(SvPV(ST(0), n_a)); + else + sphincter = nast_sphincter_new(NULL); + + if (sphincter == NULL) + XSRETURN_UNDEF; + + RETVAL = sphincter; + + OUTPUT: + RETVAL + +void +nast_sphincter_close(sphincter) + nasth *sphincter + +int +nast_options_get(sphincter) + nasth *sphincter + + PREINIT: + nast_options nast_opts; + + PPCODE: + if (nast_options_get(sphincter, &nast_opts) != -1) { + if (nast_opts.use_qcache == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + if (nast_opts.use_localdb == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + if (nast_opts.fallthrough_async == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + if (nast_opts.always_fallthrough == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + if (nast_opts.fail_once == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + if (nast_opts.no_fallthrough == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + } + +int +nast_options_set(sphincter, ...) + nasth *sphincter + + PREINIT: + nast_options nast_opts; + int i; + + CODE: + if (items == 8) { + if (SvTRUE(ST(1))) + nast_opts.use_qcache = NASTTRUE; + else + nast_opts.use_qcache = NASTFALSE; + if (SvTRUE(ST(2))) + nast_opts.use_localdb = NASTTRUE; + else + nast_opts.use_localdb = NASTFALSE; + if (SvTRUE(ST(3))) + nast_opts.fallthrough_async = NASTTRUE; + else + nast_opts.fallthrough_async = NASTFALSE; + if (SvTRUE(ST(4))) + nast_opts.always_fallthrough = NASTTRUE; + else + nast_opts.always_fallthrough = NASTFALSE; + if (SvTRUE(ST(5))) + nast_opts.fail_once = NASTTRUE; + else + nast_opts.fail_once = NASTFALSE; + if (SvTRUE(ST(6))) + nast_opts.no_fallthrough = NASTTRUE; + else + nast_opts.no_fallthrough = NASTFALSE; + + RETVAL = nast_options_set(sphincter, &nast_opts); + } else + RETVAL = -1; + + OUTPUT: + RETVAL + +SV * +nast_get_result(sphincter) + nasth *sphincter + + PREINIT: + nast_array *aa; + int i; + + PPCODE: + aa = nast_get_result(sphincter); + if (aa != NULL) { + EXTEND(SP, aa->nitems); + + for (i = 0; i < aa->nitems; i++) { + SV *item; + + item = newSVpv(aa->items[i]->strdata, + aa->items[i]->strlen); + PUSHs(sv_2mortal(item)); + } + nast_free_result(aa); + } + +int +interface_nast_qcmd(sphincter, key) + nasth *sphincter + const char *key +INTERFACE: + nast_add nast_del nast_get + +int +nast_upd(sphincter, key, ...) + nasth *sphincter + const char *key + + PREINIT: + nast_array *aa; + int i; + + CODE: + aa = nast_array_new(); + if (aa != NULL) { + for (i = 2; i < items; i++) { + char *str; + STRLEN len; + + str = (char *)SvPV(ST(i), len); + nast_array_add(aa, len, str); + } + RETVAL = nast_upd(sphincter, key, aa); + } else { + RETVAL = -1; + } + nast_array_delete(aa); + + OUTPUT: + RETVAL + +int +nast_geterr(sphincter) + nasth *sphincter + +char * +nast_errmsg(sphincter) + nasth *sphincter + +int +nast_stats(sphincter) + nasth *sphincter diff --git a/perl/.svn/text-base/build.svn-base b/perl/.svn/text-base/build.svn-base new file mode 100644 index 0000000..123a249 --- /dev/null +++ b/perl/.svn/text-base/build.svn-base @@ -0,0 +1,28 @@ +#!/bin/sh +# +# $Id: build,v 1.2 2000/05/16 19:27:05 shmit Exp $ + +if [ $# -lt 2 ]; then + echo "Usage: $0 makecmd perlflag args" 2>&1 + exit 1 +fi + +# Grab the make command +make=$1 && shift 1 + +# Should perl support be built? +perlflag=$1 && shift 1 + +if [ x"$perlflag" != x"YES" ]; then + echo "Perl support not enabled. Edit Makefiles/config to enable it." + exit 0 +fi + +if [ \! -f Makefile ]; then + # + # Build the Makefile + # + /usr/bin/env perl Makefile.PL +fi + +$make MAKE=$make $* diff --git a/perl/.svn/text-base/pm_to_blib.svn-base b/perl/.svn/text-base/pm_to_blib.svn-base new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/perl/.svn/text-base/pm_to_blib.svn-base diff --git a/perl/.svn/text-base/test.pl.svn-base b/perl/.svn/text-base/test.pl.svn-base new file mode 100644 index 0000000..6a12cbf --- /dev/null +++ b/perl/.svn/text-base/test.pl.svn-base @@ -0,0 +1,111 @@ +# $Id: test.pl,v 1.20 2001/03/23 00:06:09 shmit Exp $ +# +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +######################### We start with some black magic to print on failure. + +# Change 1..1 below to 1..last_test_to_print . +# (It may become useful if the test is moved to ./t subdirectory.) + +BEGIN { $| = 1; print "1..8\n"; } +END {print "not ok 1\n" unless $loaded;} +use NASTD; +$loaded = 1; +print "ok 1\n"; + +######################### End of black magic. + +# Insert your test code below (better if it prints "ok 13" +# (correspondingly "not ok 13") depending on the success of chunk 13 +# of the test code): + +$nasthole = &NASTD::nast_sphincter_new(); +if (!defined($nasthole)) { + print "not ok 2\n"; +} else { + print "ok 2\n"; +} + +# +# Set options +# +@setopts = (1, 1, 0, 0, 0, 1, 5); +if (&NASTD::nast_options_set($nasthole, @setopts) == -1) { + print "not ok 3\n"; +} else { + print "ok 3\n"; +} + +# +# Check options +# +@optarr = &NASTD::nast_options_get($nasthole); +$nitems = $#optarr + 1; +for ($i = 0; $i < $nitems; $i++) { + if ($optarr[$i] != $setopts[$i]) { + print "not ok 4\n"; + last; + } +} +if ($i == $nitems) { + print "ok 4\n"; +} + +# +# Perform get +# +$rv = &NASTD::nast_get($nasthole, "shmit"); +if ($rv == -1) { + print "not ok 5\n"; +} else { + print "ok 5\n"; +} + +# +# Perform update +# +@vals = ("foo", "bar", "baz"); + +$rv = &NASTD::nast_upd($nasthole, "shmit", @vals); +if ($rv == -1) { + print "not ok 6\n"; +} else { + print "ok 6\n"; +} + +# +# Verify update +# +$rv = &NASTD::nast_get($nasthole, "shmit"); +if ($rv == -1) { + print "not ok 7\n"; +} else { + print "ok 7\n"; +} + +$rv = &NASTD::nast_geterr($nasthole); +if ($rv != 0) { + print "not ok 8\n"; +} else { + print "ok 8\n"; +} + +# +# Close the sphincter when we don't need it anymore. +# +&NASTD::nast_sphincter_close($nasthole); + +# +# This grabs the results and prints them. +# +sub print_results +{ + my @vals = &NASTD::nast_get_result($nasthole); + + my $nitems = $#vals + 1; + for ($i = 0; $i < $nitems; $i++) { + my $foo = shift(@vals); + print "Result[$i]: $foo\n"; + } +} diff --git a/perl/.svn/text-base/test_fallthrough.svn-base b/perl/.svn/text-base/test_fallthrough.svn-base new file mode 100644 index 0000000..50feed8 --- /dev/null +++ b/perl/.svn/text-base/test_fallthrough.svn-base @@ -0,0 +1,38 @@ +#!/usr/bin/perl + +use NASTD; + +$nasthole = &NASTD::nast_sphincter_new(); +if (!defined($nasthole)) { + exit(1); +} + +@options = &NASTD::nast_options_get($nasthole); +if (!defined(@options)) { + print STDERR "Couldn't get options: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + exit(1); +} + +$options[5] = 1; +if (&NASTD::nast_options_set($nasthole, @options) == -1) { + print STDERR "Couldn't set options: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + exit(1); +} + +if (&NASTD::nast_get($nasthole, "asljkda") == -1) { + print STDERR "Couldn't perform get: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + exit(1); +} + +@vals = &NASTD::nast_get_result($nasthole); +$nitems = $#vals + 1; +print "Number of columns: " . $nitems . "\n"; +for ($i = 0; $i < $nitems; $i++) { + $val = shift(@vals); + print "Result[$i]: $val\n"; +} + +&NASTD::nast_sphincter_close($nasthole); diff --git a/perl/.svn/text-base/typemap.svn-base b/perl/.svn/text-base/typemap.svn-base new file mode 100644 index 0000000..c22830d --- /dev/null +++ b/perl/.svn/text-base/typemap.svn-base @@ -0,0 +1,23 @@ +const char * T_PV +nasth * T_PTROBJ +NASTD::Hole O_NASTH + +# +# Output methods +# +OUTPUT +O_NASTH + sv_setref_pv($arg, "Asshole", (void *)$var); + +# +# Input methods +# +INPUT +O_NASTH + if (sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG)) { + $var = ($type)SvIV((SV *)SvRV($arg)); + } else { + warn(\"${Package}::$func_name() --\" + \" $var is not a valid nasthole.\"); + XSRETURN_UNDEF; + } diff --git a/perl/Changes b/perl/Changes new file mode 100644 index 0000000..5158653 --- /dev/null +++ b/perl/Changes @@ -0,0 +1,5 @@ +Revision history for Perl extension ASSD. + +0.01 Thu May 11 16:58:38 2000 + - original version; created by h2xs 1.19 + diff --git a/perl/MANIFEST b/perl/MANIFEST new file mode 100644 index 0000000..1bd95ce --- /dev/null +++ b/perl/MANIFEST @@ -0,0 +1,6 @@ +NASTD.pm +NASTD.xs +Changes +MANIFEST +Makefile.PL +test.pl diff --git a/perl/Makefile.PL b/perl/Makefile.PL new file mode 100644 index 0000000..a6d8f02 --- /dev/null +++ b/perl/Makefile.PL @@ -0,0 +1,11 @@ +use ExtUtils::MakeMaker; +# See lib/ExtUtils/MakeMaker.pm for details of how to influence +# the contents of the Makefile that is written. +WriteMakefile( + 'NAME' => 'NASTD', + 'VERSION_FROM' => 'NASTD.pm', # finds $VERSION + 'LIBS' => ['-L../client -lnast'], # e.g., '-lm' + 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING' + 'INC' => '', # e.g., '-I/usr/include/other' + 'depend' => {'NAST.xs' => '../client/libnast.a'} +); diff --git a/perl/Makefile.old b/perl/Makefile.old new file mode 100644 index 0000000..d764b63 --- /dev/null +++ b/perl/Makefile.old @@ -0,0 +1,761 @@ +# This Makefile is for the NASTD extension to perl. +# +# It was generated automatically by MakeMaker version +# 5.4302 (Revision: 1.222) from the contents of +# Makefile.PL. Don't edit this file, edit Makefile.PL instead. +# +# ANY CHANGES MADE HERE WILL BE LOST! +# +# MakeMaker ARGV: () +# +# MakeMaker Parameters: + +# DEFINE => q[] +# INC => q[] +# LIBS => [q[-L../client -lnast]] +# NAME => q[NASTD] +# VERSION_FROM => q[NASTD.pm] +# depend => { NAST.xs=>q[../client/libnast.a] } + +# --- MakeMaker post_initialize section: + + +# --- MakeMaker const_config section: + +# These definitions are from config.sh (via /usr/local/lib/perl5/5.00503/sun4-solaris/Config.pm) + +# They may have been overridden via Makefile.PL or on the command line +AR = ar +CC = gcc -B/usr/ccs/bin/ +CCCDLFLAGS = -fPIC +CCDLFLAGS = +DLEXT = so +DLSRC = dl_dlopen.xs +LD = gcc -B/usr/ccs/bin/ +LDDLFLAGS = -G -L/usr/local/lib +LDFLAGS = -L/usr/local/lib +LIBC = /lib/libc.so +LIB_EXT = .a +OBJ_EXT = .o +OSNAME = solaris +OSVERS = 2.6 +RANLIB = : +SO = so +EXE_EXT = + + +# --- MakeMaker constants section: +AR_STATIC_ARGS = cr +NAME = NASTD +DISTNAME = NASTD +NAME_SYM = NASTD +VERSION = 0.01 +VERSION_SYM = 0_01 +XS_VERSION = 0.01 +INST_BIN = blib/bin +INST_EXE = blib/script +INST_LIB = blib/lib +INST_ARCHLIB = blib/arch +INST_SCRIPT = blib/script +PREFIX = /usr/local +INSTALLDIRS = site +INSTALLPRIVLIB = $(PREFIX)/lib/perl5/5.00503 +INSTALLARCHLIB = $(PREFIX)/lib/perl5/5.00503/sun4-solaris +INSTALLSITELIB = $(PREFIX)/lib/perl5/site_perl/5.005 +INSTALLSITEARCH = $(PREFIX)/lib/perl5/site_perl/5.005/sun4-solaris +INSTALLBIN = $(PREFIX)/bin +INSTALLSCRIPT = $(PREFIX)/bin +PERL_LIB = /usr/local/lib/perl5/5.00503 +PERL_ARCHLIB = /usr/local/lib/perl5/5.00503/sun4-solaris +SITELIBEXP = /usr/local/lib/perl5/site_perl/5.005 +SITEARCHEXP = /usr/local/lib/perl5/site_perl/5.005/sun4-solaris +LIBPERL_A = libperl.a +FIRST_MAKEFILE = Makefile +MAKE_APERL_FILE = Makefile.aperl +PERLMAINCC = $(CC) +PERL_INC = /usr/local/lib/perl5/5.00503/sun4-solaris/CORE +PERL = /opt/bin/perl +FULLPERL = /opt/bin/perl + +VERSION_MACRO = VERSION +DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\" +XS_VERSION_MACRO = XS_VERSION +XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\" + +MAKEMAKER = /usr/local/lib/perl5/5.00503/ExtUtils/MakeMaker.pm +MM_VERSION = 5.4302 + +# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle). +# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle) +# ROOTEXT = Directory part of FULLEXT with leading slash (eg /DBD) !!! Deprecated from MM 5.32 !!! +# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar) +# DLBASE = Basename part of dynamic library. May be just equal BASEEXT. +FULLEXT = NASTD +BASEEXT = NASTD +DLBASE = $(BASEEXT) +VERSION_FROM = NASTD.pm +INC = +DEFINE = +OBJECT = $(BASEEXT)$(OBJ_EXT) +LDFROM = $(OBJECT) +LINKTYPE = dynamic + +# Handy lists of source code files: +XS_FILES= NASTD.xs +C_FILES = NASTD.c +O_FILES = NASTD.o +H_FILES = +MAN1PODS = +MAN3PODS = NASTD.pm +INST_MAN1DIR = blib/man1 +INSTALLMAN1DIR = /usr/local/man/man1 +MAN1EXT = 1 +INST_MAN3DIR = blib/man3 +INSTALLMAN3DIR = /usr/local/lib/perl5/5.00503/man/man3 +MAN3EXT = 3 +PERM_RW = 644 +PERM_RWX = 755 + +# work around a famous dec-osf make(1) feature(?): +makemakerdflt: all + +.SUFFIXES: .xs .c .C .cpp .cxx .cc $(OBJ_EXT) + +# Nick wanted to get rid of .PRECIOUS. I don't remember why. I seem to recall, that +# some make implementations will delete the Makefile when we rebuild it. Because +# we call false(1) when we rebuild it. So make(1) is not completely wrong when it +# does so. Our milage may vary. +# .PRECIOUS: Makefile # seems to be not necessary anymore + +.PHONY: all config static dynamic test linkext manifest + +# Where is the Config information that we are using/depend on +CONFIGDEP = $(PERL_ARCHLIB)/Config.pm $(PERL_INC)/config.h + +# Where to put things: +INST_LIBDIR = $(INST_LIB) +INST_ARCHLIBDIR = $(INST_ARCHLIB) + +INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT) +INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT) + +INST_STATIC = $(INST_ARCHAUTODIR)/$(BASEEXT)$(LIB_EXT) +INST_DYNAMIC = $(INST_ARCHAUTODIR)/$(DLBASE).$(DLEXT) +INST_BOOT = $(INST_ARCHAUTODIR)/$(BASEEXT).bs + +EXPORT_LIST = + +PERL_ARCHIVE = + +TO_INST_PM = NASTD.pm + +PM_TO_BLIB = NASTD.pm \ + $(INST_LIBDIR)/NASTD.pm + + +# --- MakeMaker tool_autosplit section: + +# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto +AUTOSPLITFILE = $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e 'use AutoSplit;autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1) ;' + + +# --- MakeMaker tool_xsubpp section: + +XSUBPPDIR = /usr/local/lib/perl5/5.00503/ExtUtils +XSUBPP = $(XSUBPPDIR)/xsubpp +XSPROTOARG = +XSUBPPDEPS = $(XSUBPPDIR)/typemap typemap +XSUBPPARGS = -typemap $(XSUBPPDIR)/typemap -typemap typemap + + +# --- MakeMaker tools_other section: + +SHELL = /bin/sh +CHMOD = chmod +CP = cp +LD = gcc -B/usr/ccs/bin/ +MV = mv +NOOP = $(SHELL) -c true +RM_F = rm -f +RM_RF = rm -rf +TEST_F = test -f +TOUCH = touch +UMASK_NULL = umask 0 +DEV_NULL = > /dev/null 2>&1 + +# The following is a portable way to say mkdir -p +# To see which directories are created, change the if 0 to if 1 +MKPATH = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e mkpath + +# This helps us to minimize the effect of the .exists files A yet +# better solution would be to have a stable file in the perl +# distribution with a timestamp of zero. But this solution doesn't +# need any changes to the core distribution and works with older perls +EQUALIZE_TIMESTAMP = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e eqtime + +# Here we warn users that an old packlist file was found somewhere, +# and that they should call some uninstall routine +WARN_IF_OLD_PACKLIST = $(PERL) -we 'exit unless -f $$ARGV[0];' \ +-e 'print "WARNING: I have found an old package in\n";' \ +-e 'print "\t$$ARGV[0].\n";' \ +-e 'print "Please make sure the two installations are not conflicting\n";' + +UNINST=0 +VERBINST=1 + +MOD_INSTALL = $(PERL) -I$(INST_LIB) -I$(PERL_LIB) -MExtUtils::Install \ +-e "install({@ARGV},'$(VERBINST)',0,'$(UNINST)');" + +DOC_INSTALL = $(PERL) -e '$$\="\n\n";' \ +-e 'print "=head2 ", scalar(localtime), ": C<", shift, ">", " L<", shift, ">";' \ +-e 'print "=over 4";' \ +-e 'while (defined($$key = shift) and defined($$val = shift)){print "=item *";print "C<$$key: $$val>";}' \ +-e 'print "=back";' + +UNINSTALL = $(PERL) -MExtUtils::Install \ +-e 'uninstall($$ARGV[0],1,1); print "\nUninstall is deprecated. Please check the";' \ +-e 'print " packlist above carefully.\n There may be errors. Remove the";' \ +-e 'print " appropriate files manually.\n Sorry for the inconveniences.\n"' + + +# --- MakeMaker dist section: + +DISTVNAME = $(DISTNAME)-$(VERSION) +TAR = tar +TARFLAGS = cvf +ZIP = zip +ZIPFLAGS = -r +COMPRESS = gzip --best +SUFFIX = .gz +SHAR = shar +PREOP = @$(NOOP) +POSTOP = @$(NOOP) +TO_UNIX = @$(NOOP) +CI = ci -u +RCS_LABEL = rcs -Nv$(VERSION_SYM): -q +DIST_CP = best +DIST_DEFAULT = tardist + + +# --- MakeMaker macro section: + + +# --- MakeMaker depend section: +NAST.xs: ../client/libnast.a + + +# --- MakeMaker cflags section: + +CCFLAGS = -O2 -pipe -I/usr/local/include +OPTIMIZE = -O +PERLTYPE = +LARGE = +SPLIT = + + +# --- MakeMaker const_loadlibs section: + +# NASTD might depend on some other libraries: +# See ExtUtils::Liblist for details +# +EXTRALIBS = -L/usr/home/shmit/src/nastd/perl/../client -lnast +LDLOADLIBS = -L/usr/home/shmit/src/nastd/perl/../client -lnast +BSLOADLIBS = +LD_RUN_PATH = /usr/home/shmit/src/nastd/perl/../client + + +# --- MakeMaker const_cccmd section: +CCCMD = $(CC) -c $(INC) $(CCFLAGS) $(OPTIMIZE) \ + $(PERLTYPE) $(LARGE) $(SPLIT) $(DEFINE_VERSION) \ + $(XS_DEFINE_VERSION) + +# --- MakeMaker post_constants section: + + +# --- MakeMaker pasthru section: + +PASTHRU = LIB="$(LIB)"\ + LIBPERL_A="$(LIBPERL_A)"\ + LINKTYPE="$(LINKTYPE)"\ + PREFIX="$(PREFIX)"\ + OPTIMIZE="$(OPTIMIZE)" + + +# --- MakeMaker c_o section: + +.c$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.c + +.C$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.C + +.cpp$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.cpp + +.cxx$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.cxx + +.cc$(OBJ_EXT): + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.cc + + +# --- MakeMaker xs_c section: + +.xs.c: + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $*.xs >xstmp.c && $(MV) xstmp.c $*.c + + +# --- MakeMaker xs_o section: + +.xs$(OBJ_EXT): + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $*.xs >xstmp.c && $(MV) xstmp.c $*.c + $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.c + + +# --- MakeMaker top_targets section: + +#all :: config $(INST_PM) subdirs linkext manifypods + +all :: pure_all manifypods + @$(NOOP) + +pure_all :: config pm_to_blib subdirs linkext + @$(NOOP) + +subdirs :: $(MYEXTLIB) + @$(NOOP) + +config :: Makefile $(INST_LIBDIR)/.exists + @$(NOOP) + +config :: $(INST_ARCHAUTODIR)/.exists + @$(NOOP) + +config :: $(INST_AUTODIR)/.exists + @$(NOOP) + +config :: Version_check + @$(NOOP) + + +$(INST_AUTODIR)/.exists :: /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h + @$(MKPATH) $(INST_AUTODIR) + @$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h $(INST_AUTODIR)/.exists + + -@$(CHMOD) $(PERM_RWX) $(INST_AUTODIR) + +$(INST_LIBDIR)/.exists :: /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h + @$(MKPATH) $(INST_LIBDIR) + @$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h $(INST_LIBDIR)/.exists + + -@$(CHMOD) $(PERM_RWX) $(INST_LIBDIR) + +$(INST_ARCHAUTODIR)/.exists :: /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h + @$(MKPATH) $(INST_ARCHAUTODIR) + @$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h $(INST_ARCHAUTODIR)/.exists + + -@$(CHMOD) $(PERM_RWX) $(INST_ARCHAUTODIR) + +config :: $(INST_MAN3DIR)/.exists + @$(NOOP) + + +$(INST_MAN3DIR)/.exists :: /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h + @$(MKPATH) $(INST_MAN3DIR) + @$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00503/sun4-solaris/CORE/perl.h $(INST_MAN3DIR)/.exists + + -@$(CHMOD) $(PERM_RWX) $(INST_MAN3DIR) + +help: + perldoc ExtUtils::MakeMaker + +Version_check: + @$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) \ + -MExtUtils::MakeMaker=Version_check \ + -e "Version_check('$(MM_VERSION)')" + + +# --- MakeMaker linkext section: + +linkext :: $(LINKTYPE) + @$(NOOP) + + +# --- MakeMaker dlsyms section: + + +# --- MakeMaker dynamic section: + +## $(INST_PM) has been moved to the all: target. +## It remains here for awhile to allow for old usage: "make dynamic" +#dynamic :: Makefile $(INST_DYNAMIC) $(INST_BOOT) $(INST_PM) +dynamic :: Makefile $(INST_DYNAMIC) $(INST_BOOT) + @$(NOOP) + + +# --- MakeMaker dynamic_bs section: + +BOOTSTRAP = NASTD.bs + +# As Mkbootstrap might not write a file (if none is required) +# we use touch to prevent make continually trying to remake it. +# The DynaLoader only reads a non-empty file. +$(BOOTSTRAP): Makefile $(INST_ARCHAUTODIR)/.exists + @echo "Running Mkbootstrap for $(NAME) ($(BSLOADLIBS))" + @$(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" \ + -MExtUtils::Mkbootstrap \ + -e "Mkbootstrap('$(BASEEXT)','$(BSLOADLIBS)');" + @$(TOUCH) $(BOOTSTRAP) + $(CHMOD) $(PERM_RW) $@ + +$(INST_BOOT): $(BOOTSTRAP) $(INST_ARCHAUTODIR)/.exists + @rm -rf $(INST_BOOT) + -cp $(BOOTSTRAP) $(INST_BOOT) + $(CHMOD) $(PERM_RW) $@ + + +# --- MakeMaker dynamic_lib section: + +# This section creates the dynamically loadable $(INST_DYNAMIC) +# from $(OBJECT) and possibly $(MYEXTLIB). +ARMAYBE = : +OTHERLDFLAGS = +INST_DYNAMIC_DEP = + +$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)/.exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP) + LD_RUN_PATH="$(LD_RUN_PATH)" $(LD) -o $@ -R/usr/home/shmit/src/nastd/perl/../client $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) $(EXPORT_LIST) + $(CHMOD) $(PERM_RWX) $@ + + +# --- MakeMaker static section: + +## $(INST_PM) has been moved to the all: target. +## It remains here for awhile to allow for old usage: "make static" +#static :: Makefile $(INST_STATIC) $(INST_PM) +static :: Makefile $(INST_STATIC) + @$(NOOP) + + +# --- MakeMaker static_lib section: + +$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)/.exists + $(RM_RF) $@ + $(AR) $(AR_STATIC_ARGS) $@ $(OBJECT) && $(RANLIB) $@ + $(CHMOD) $(PERM_RWX) $@ + @echo "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)/extralibs.ld + + + +# --- MakeMaker manifypods section: +POD2MAN_EXE = /usr/local/bin/pod2man +POD2MAN = $(PERL) -we '%m=@ARGV;for (keys %m){' \ +-e 'next if -e $$m{$$_} && -M $$m{$$_} < -M $$_ && -M $$m{$$_} < -M "Makefile";' \ +-e 'print "Manifying $$m{$$_}\n";' \ +-e 'system(qq[$$^X ].q["-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" $(POD2MAN_EXE) ].qq[$$_>$$m{$$_}])==0 or warn "Couldn\047t install $$m{$$_}\n";' \ +-e 'chmod(oct($(PERM_RW))), $$m{$$_} or warn "chmod $(PERM_RW) $$m{$$_}: $$!\n";}' + +manifypods : pure_all NASTD.pm + @$(POD2MAN) \ + NASTD.pm \ + $(INST_MAN3DIR)/NASTD.$(MAN3EXT) + +# --- MakeMaker processPL section: + + +# --- MakeMaker installbin section: + + +# --- MakeMaker subdirs section: + +# none + +# --- MakeMaker clean section: + +# Delete temporary files but do not touch installed files. We don't delete +# the Makefile here so a later make realclean still has a makefile to use. + +clean :: + -rm -rf NASTD.c ./blib $(MAKE_APERL_FILE) $(INST_ARCHAUTODIR)/extralibs.all perlmain.c mon.out core so_locations pm_to_blib *~ */*~ */*/*~ *$(OBJ_EXT) *$(LIB_EXT) perl.exe $(BOOTSTRAP) $(BASEEXT).bso $(BASEEXT).def $(BASEEXT).exp + -mv Makefile Makefile.old $(DEV_NULL) + + +# --- MakeMaker realclean section: + +# Delete temporary files (via clean) and also delete installed files +realclean purge :: clean + rm -rf $(INST_AUTODIR) $(INST_ARCHAUTODIR) + rm -f $(INST_DYNAMIC) $(INST_BOOT) + rm -f $(INST_STATIC) + rm -f $(INST_LIBDIR)/NASTD.pm + rm -rf Makefile Makefile.old + + +# --- MakeMaker dist_basics section: + +distclean :: realclean distcheck + +distcheck : + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=fullcheck \ + -e fullcheck + +skipcheck : + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=skipcheck \ + -e skipcheck + +manifest : + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=mkmanifest \ + -e mkmanifest + + +# --- MakeMaker dist_core section: + +dist : $(DIST_DEFAULT) + @$(PERL) -le 'print "Warning: Makefile possibly out of date with $$vf" if ' \ + -e '-e ($$vf="$(VERSION_FROM)") and -M $$vf < -M "Makefile";' + +tardist : $(DISTVNAME).tar$(SUFFIX) + +zipdist : $(DISTVNAME).zip + +$(DISTVNAME).tar$(SUFFIX) : distdir + $(PREOP) + $(TO_UNIX) + $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(COMPRESS) $(DISTVNAME).tar + $(POSTOP) + +$(DISTVNAME).zip : distdir + $(PREOP) + $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(POSTOP) + +uutardist : $(DISTVNAME).tar$(SUFFIX) + uuencode $(DISTVNAME).tar$(SUFFIX) \ + $(DISTVNAME).tar$(SUFFIX) > \ + $(DISTVNAME).tar$(SUFFIX)_uu + +shdist : distdir + $(PREOP) + $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar + $(RM_RF) $(DISTVNAME) + $(POSTOP) + + +# --- MakeMaker dist_dir section: + +distdir : + $(RM_RF) $(DISTVNAME) + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=manicopy,maniread \ + -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');" + + +# --- MakeMaker dist_test section: + +disttest : distdir + cd $(DISTVNAME) && $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) Makefile.PL + cd $(DISTVNAME) && $(MAKE) + cd $(DISTVNAME) && $(MAKE) test + + +# --- MakeMaker dist_ci section: + +ci : + $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=maniread \ + -e "@all = keys %{ maniread() };" \ + -e 'print("Executing $(CI) @all\n"); system("$(CI) @all");' \ + -e 'print("Executing $(RCS_LABEL) ...\n"); system("$(RCS_LABEL) @all");' + + +# --- MakeMaker install section: + +install :: all pure_install doc_install + +install_perl :: all pure_perl_install doc_perl_install + +install_site :: all pure_site_install doc_site_install + +install_ :: install_site + @echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +pure_install :: pure_$(INSTALLDIRS)_install + +doc_install :: doc_$(INSTALLDIRS)_install + @echo Appending installation info to $(INSTALLARCHLIB)/perllocal.pod + +pure__install : pure_site_install + @echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +doc__install : doc_site_install + @echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +pure_perl_install :: + @$(MOD_INSTALL) \ + read $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist \ + write $(INSTALLARCHLIB)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(INSTALLPRIVLIB) \ + $(INST_ARCHLIB) $(INSTALLARCHLIB) \ + $(INST_BIN) $(INSTALLBIN) \ + $(INST_SCRIPT) $(INSTALLSCRIPT) \ + $(INST_MAN1DIR) $(INSTALLMAN1DIR) \ + $(INST_MAN3DIR) $(INSTALLMAN3DIR) + @$(WARN_IF_OLD_PACKLIST) \ + $(SITEARCHEXP)/auto/$(FULLEXT) + + +pure_site_install :: + @$(MOD_INSTALL) \ + read $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist \ + write $(INSTALLSITEARCH)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(INSTALLSITELIB) \ + $(INST_ARCHLIB) $(INSTALLSITEARCH) \ + $(INST_BIN) $(INSTALLBIN) \ + $(INST_SCRIPT) $(INSTALLSCRIPT) \ + $(INST_MAN1DIR) $(INSTALLMAN1DIR) \ + $(INST_MAN3DIR) $(INSTALLMAN3DIR) + @$(WARN_IF_OLD_PACKLIST) \ + $(PERL_ARCHLIB)/auto/$(FULLEXT) + +doc_perl_install :: + -@$(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLPRIVLIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(INSTALLARCHLIB)/perllocal.pod + +doc_site_install :: + -@$(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLSITELIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(INSTALLARCHLIB)/perllocal.pod + + +uninstall :: uninstall_from_$(INSTALLDIRS)dirs + +uninstall_from_perldirs :: + @$(UNINSTALL) $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist + +uninstall_from_sitedirs :: + @$(UNINSTALL) $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist + + +# --- MakeMaker force section: +# Phony target to force checking subdirectories. +FORCE: + @$(NOOP) + + +# --- MakeMaker perldepend section: + +PERL_HDRS = \ +$(PERL_INC)/EXTERN.h $(PERL_INC)/gv.h $(PERL_INC)/pp.h \ +$(PERL_INC)/INTERN.h $(PERL_INC)/handy.h $(PERL_INC)/proto.h \ +$(PERL_INC)/XSUB.h $(PERL_INC)/hv.h $(PERL_INC)/regcomp.h \ +$(PERL_INC)/av.h $(PERL_INC)/keywords.h $(PERL_INC)/regexp.h \ +$(PERL_INC)/config.h $(PERL_INC)/mg.h $(PERL_INC)/scope.h \ +$(PERL_INC)/cop.h $(PERL_INC)/op.h $(PERL_INC)/sv.h \ +$(PERL_INC)/cv.h $(PERL_INC)/opcode.h $(PERL_INC)/unixish.h \ +$(PERL_INC)/dosish.h $(PERL_INC)/patchlevel.h $(PERL_INC)/util.h \ +$(PERL_INC)/embed.h $(PERL_INC)/perl.h $(PERL_INC)/iperlsys.h \ +$(PERL_INC)/form.h $(PERL_INC)/perly.h + +$(OBJECT) : $(PERL_HDRS) + +NASTD.c : $(XSUBPPDEPS) + + +# --- MakeMaker makefile section: + +$(OBJECT) : $(FIRST_MAKEFILE) + +# We take a very conservative approach here, but it\'s worth it. +# We move Makefile to Makefile.old here to avoid gnu make looping. +Makefile : Makefile.PL $(CONFIGDEP) + @echo "Makefile out-of-date with respect to $?" + @echo "Cleaning current config before rebuilding Makefile..." + -@$(RM_F) Makefile.old + -@$(MV) Makefile Makefile.old + -$(MAKE) -f Makefile.old clean $(DEV_NULL) || $(NOOP) + $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" Makefile.PL + @echo "==> Your Makefile has been rebuilt. <==" + @echo "==> Please rerun the make command. <==" + false + +# To change behavior to :: would be nice, but would break Tk b9.02 +# so you find such a warning below the dist target. +#Makefile :: $(VERSION_FROM) +# @echo "Warning: Makefile possibly out of date with $(VERSION_FROM)" + + +# --- MakeMaker staticmake section: + +# --- MakeMaker makeaperl section --- +MAP_TARGET = perl +FULLPERL = /opt/bin/perl + +$(MAP_TARGET) :: static $(MAKE_APERL_FILE) + $(MAKE) -f $(MAKE_APERL_FILE) $@ + +$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) + @echo Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) + @$(PERL) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) \ + Makefile.PL DIR= \ + MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ + MAKEAPERL=1 NORECURS=1 CCCDLFLAGS= + + +# --- MakeMaker test section: + +TEST_VERBOSE=0 +TEST_TYPE=test_$(LINKTYPE) +TEST_FILE = test.pl +TEST_FILES = +TESTDB_SW = -d + +testdb :: testdb_$(LINKTYPE) + +test :: $(TEST_TYPE) + +test_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERL) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(TEST_FILE) + +testdb_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERL) $(TESTDB_SW) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(TEST_FILE) + +test_ : test_dynamic + +test_static :: pure_all $(MAP_TARGET) + PERL_DL_NONLAZY=1 ./$(MAP_TARGET) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(TEST_FILE) + +testdb_static :: pure_all $(MAP_TARGET) + PERL_DL_NONLAZY=1 ./$(MAP_TARGET) $(TESTDB_SW) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(TEST_FILE) + + + +# --- MakeMaker ppd section: +# Creates a PPD (Perl Package Description) for a binary distribution. +ppd: + @$(PERL) -e "print qq{<SOFTPKG NAME=\"NASTD\" VERSION=\"0,01,0,0\">\n}. qq{\t<TITLE>NASTD</TITLE>\n}. qq{\t<ABSTRACT></ABSTRACT>\n}. qq{\t<AUTHOR></AUTHOR>\n}. qq{\t<IMPLEMENTATION>\n}. qq{\t\t<OS NAME=\"$(OSNAME)\" />\n}. qq{\t\t<ARCHITECTURE NAME=\"sun4-solaris\" />\n}. qq{\t\t<CODEBASE HREF=\"\" />\n}. qq{\t</IMPLEMENTATION>\n}. qq{</SOFTPKG>\n}" > NASTD.ppd + +# --- MakeMaker pm_to_blib section: + +pm_to_blib: $(TO_INST_PM) + @$(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" \ + "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -MExtUtils::Install \ + -e "pm_to_blib({qw{$(PM_TO_BLIB)}},'$(INST_LIB)/auto')" + @$(TOUCH) $@ + + +# --- MakeMaker selfdocument section: + + +# --- MakeMaker postamble section: + + +# End. diff --git a/perl/NASTD.pm b/perl/NASTD.pm new file mode 100644 index 0000000..70be2ff --- /dev/null +++ b/perl/NASTD.pm @@ -0,0 +1,313 @@ +# $Id: NASTD.pm,v 1.7 2001/10/29 11:18:20 shmit Exp $ + +package NASTD; + +use strict; +use Carp; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD); + +require Exporter; +require DynaLoader; +require AutoLoader; + +@ISA = qw(Exporter DynaLoader); +# Items to export into callers namespace by default. Note: do not export +# names by default without a very good reason. Use EXPORT_OK instead. +# Do not simply export all your public functions/methods/constants. +@EXPORT = qw( + NAST_OK + NAST_SERVER_GONE + NAST_NOMEM + NAST_UNKNOWN_RESPONSE + NAST_TIMEDOUT + NAST_UNKNOWN_OPT + NAST_SERVER_ERR +); +$VERSION = '0.01'; + +sub AUTOLOAD { + # This AUTOLOAD is used to 'autoload' constants from the constant() + # XS function. If a constant is not found then control is passed + # to the AUTOLOAD in AutoLoader. + + my $constname; + ($constname = $AUTOLOAD) =~ s/.*:://; + croak "& not defined" if $constname eq 'constant'; + my $val = constant($constname, @_ ? $_[0] : 0); + if ($! != 0) { + if ($! =~ /Invalid/) { + $AutoLoader::AUTOLOAD = $AUTOLOAD; + goto &AutoLoader::AUTOLOAD; + } + else { + croak "Your vendor has not defined NASTD macro $constname"; + } + } + no strict 'refs'; + *$AUTOLOAD = sub () { $val }; + goto &$AUTOLOAD; +} + +bootstrap NASTD $VERSION; + +# Preloaded methods go here. + +# Autoload methods go after =cut, and are processed by the autosplit program. + +1; +__END__ +# Below is the stub of documentation for your module. You better edit it! + +=head1 NAME + +NASTD - Low level Perl extension for NASTD access methods + +=head1 SYNOPSIS + + use NASTD; + + $nasthole = &NASTD::nast_sphincter_new(); + &NASTD::nast_sphincter_close($nasthole); + + $rv = &NASTD::nast_options_get($nasthole); + $rv = &NASTD::nast_options_set($nasthole, @options); + + @values = &NASTD::nast_get_result($nasthole); + + $rv = &NASTD::nast_add($sphincter, $key); + $rv = &NASTD::nast_del($sphincter, $key); + $rv = &NASTD::nast_get($sphincter, $key); + $rv = &NASTD::nast_upd($sphincter, $key, $values); + + $rv = &NASTD::nast_stats($sphincter); + + $errcode = &NASTD::nast_geterr($sphincter); + $errstring = &NASTD::nast_errmsg($sphincter); + +=head1 DESCRIPTION + +The Perl NASTD module allows access to the NASTD server via a Perl +interface. It allows you to do anything you could do through C, such as +get records, update records, or delete records. It also allows setting +of various NASTD connection options, as you would through C. + +=head2 Opening a sphincter + +To do any work with NASTD at all, you must first open a sphincter, +through which you talk to your NASNASTole. This is fairly +straightforward: just call C<nast_sphincter_new()> and save the +returned handle. When you're done with the connection to your NAST, call +C<nast_sphincter_close()> to terminate it and free all memory of it. + +You may specify an optional argument, which points to the unix domain +socket name that you wish to use. By default, this is set to +"/tmp/nastd.sock". + +When an error occurs in C<nast_sphincter_new()>, you cannot call +C<nast_geterr()> since there's no sphincter with which to call it. +Instead, an error message will be printed on B<STDERR> for you to +diagnose, and the return value will be undefined. + +=head2 Checking errors + +There are many places during an NASTD session that errors can be +generated. To check for the presense of an error, call C<nast_geterr()> +with the sphincter returned from C<nast_sphincter_new()>. This will +return an error code, which is defined below under B<CONSTANTS>. + +If you would rather a printable string be returned, you can call +C<nast_errmsg()> with an open sphincter, and a printable string will be +returned. + +=head2 Performing a query + +Once you have an open sphincter, obtained via C<nast_sphincter_new()>, +you can start to query it with C<nast_add()>, C<nast_del()>, +C<nast_get()>, and C<nast_upd()>. + +The B<$key> is just that, a case-sensitive key for the database you're +querying. It's function depends on which query function you're using: + + Function Key Meaning + -------- ----------- + nast_add() Add this key to NASTD, with default values. + nast_del() Delete this key from NASTD. + nast_get() Return values associated with this key. + nast_upd() Update this key in NASTD with my values. + +All four of these functions return a status. If everything went okay, +then 0 is returned, otherwise -1 is returned, and you should check for +an error with C<nast_geterr()>. + +In the case of C<nast_add()>, C<nast_del()>, and C<nast_upd()> all you +need to do is call the query function and check for errors. If there +are no errors, then everything went fine. + +However, in the case of C<nast_get()>, you probably want the values +nastociated with the query you made. To get these values, you have to +call C<nast_get_result()>, which returns an array of values. + +=head2 Updating the database via C<nast_upd()> + +C<nast_upd()> works like the other query functions, except that in +addition to the key, you also need to pass an array of values. The +array needs to have the same number of elements as the NASTD database +has, and the elements should be in the same order as that specified in +the special key, "B<_VALUES_>" (see B<Key concepts and values>, +below). + +If the key you are trying to update does not exist, the server creates +it and gives it the values you specified in your value array. For this +reason C<nast_upd()> is preferable to C<nast_add()>. In fact, +C<nast_add()> may not exist very much longer. + +=head2 Key concepts and values + +It is recommended that before you try to do any real work with a +particular NASTD suppository, you first investigate the contents of the +special keys B<_KEY_> and B<_VALUES_>. You can do a regular query on +them using C<nast_get($nasthole, "_VALUES_")> followed by +C<nast_get_result()> to investigate their columns. + + Special Key Value Meaning + ----------- ------------- + _KEY_ The type of key the database is keyed on, + e.g., "username" would mean this database + is a username -> _VALUES_ mapping. + _VALUES_ The data being stored for every key in + the database. The order here is important, + as it's the same order that you'll get + when calling nast_get_result(). + _DELIM_ Only used internally to the NASTD server. + +As noted above, the B<_VALUES_> key shows what data you can find in the +NASTD database, as well as the order it is returned in. This is why you +should investigate this key before trying to do any real work with +NASTD. You have to know what columns mean what values for any real +decision making to be done. + +=head2 Server options + +In order to fine-tune server performance and behaviour, it is possible +to set various server-side options through the C<nast_options_get()> and +C<nast_options_set()> APIs. + +The interface is a bit clumsy at the low level - you pass in an array +to C<nast_options_set()> which has the options in a specific order, and +you get an array back from C<nast_options_get()> which contains the +options in a specific order. + +It is recommended that before you call C<nast_options_set()> that you +first obtain the default options from the server through +C<nast_options_get()> and manipulate the values you care about. Then +pass that array back to C<nast_options_set()>. + +The options you can set are as follows (remember to keep this order!): + + Index C Option Name Meaning (type) + ----- ------------- -------------- + 0 use_qcache Whether or not to use the + in-memory query cache. (BOOL) + 1 use_localdb Whether or not to use the on-disk + database. (BOOL) + 2 fallthrough_async Whether or not to use an + asynchronous API for fallthrough + queries. (BOOL) + 3 always_fallthrough Whether or not to always check + the fallthrough cache over the + local ones. Setting this to 1 + is the same as setting use_qcache + and use_localdb to 0. (BOOL) + 4 fail_once Whether or not to check a query + in the local and in-memory storage + once, and fail if the result isn't + found the first time, then defer + the next query to the fallthrough + queue. (BOOL) + 5 no_fallthrough Disable fallthrough queriers to + MySQL server. (BOOL) + +=head1 STATISTICS + +The C<nast_stats()> function is used to gather server statistics. First +you call C<nast_stats()>, which grabs the statistics and stores them as +a result. Then you call C<nast_getresult()> as you would for a query. + +The statistics come back in a human readable array, suitable for printing. + +=head1 CONSTANTS + +The only constants returned are via C<nast_geterr()>: + + Error Code Meaning + ---------- ------- + NAST_OK No errors occured. + NAST_SERVER_GONE The connection to the server no longer + exists. + NAST_NOMEM The client has run out of memory performing + an operation. + NAST_UNKNOWN_RESPONSE The server sent us a response we can't + understand. + NAST_TIMEDOUT The soft timeout on a query has elapsed. + This normally means the server is a bit + bogged down, and the query should be + retried. + NAST_UNKNOWN_OPT The server sent us an unknown option or + we tried to set an unknown option. + NAST_SERVER_ERR Generic server side error. Check + nast_errmsg() for more details. + +=head1 SAMPLE PROGRAM + + #!/usr/bin/env perl + + use NASTD; + + $nasthole = &NASTD::nast_sphincter_new(); + if (!defined($nasthole)) { + # Error message already printed. + exit(1); + } + + # Don't fallthrough to MySQL for this query. + # First we get the default options from the server, then tweak + # the ones we care about, and update the server with our options. + @options = &NASTD::nast_options_get($nasthole); + if (!defined(@options)) { + print STDERR "Couldn't get options: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + } + $options[5] = 1; + + if (&NASTD::nast_options_set($nasthole, @options) == -1) { + print STDERR "Couldn't set options: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + } + + # Get some values. + if (&NASTD::nast_get($nasthole, "shmit") == -1) { + print STDERR "Couldn't perform get: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + &NASTD::nast_close_sphincter($nasthole); + exit(1); + } + + @vals = &NASTD::nast_get_result($nasthole); + $nitems = $#vals + 1; + print "Number of columns: $nitems.\n"; + for ($i = 0; $i < $nitems; $i++) { + $val = shift(@vals); + print "Result[$i]: $val\n"; + } + + &NASTD::nast_sphincter_close($nasthole); + +=head1 BUGS + +fail_once behaviour is not working as of this writing. + +=head1 AUTHOR + +Brian Cully <L<shmit@rcn.com|mailto:shmit@rcn.com>> + +=cut diff --git a/perl/NASTD.xs b/perl/NASTD.xs new file mode 100644 index 0000000..e7b1179 --- /dev/null +++ b/perl/NASTD.xs @@ -0,0 +1,278 @@ +/* $Id: NASTD.xs,v 1.5 2001/10/29 11:18:20 shmit Exp $ */ + +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +#include "../include/nastd.h" + +#include "include/nastdxs.def" + +static int +not_here(char *s) +{ + croak("%s not implemented on this architecture", s); + return -1; +} + +static double +constant(char *name, int arg) +{ + errno = 0; + switch (*name) { + case 'A': + if (strEQ(name, "NAST_OK")) + return NAST_OK; + else if (strEQ(name, "NAST_SERVER_GONE")) + return NAST_SERVER_GONE; + else if (strEQ(name, "NAST_NOMEM")) + return NAST_NOMEM; + else if (strEQ(name, "NAST_UNNKNOWN_RESPONSE")) + return NAST_UNKNOWN_RESPONSE; + else if (strEQ(name, "NAST_TIMEDOUT")) + return NAST_TIMEDOUT; + else if (strEQ(name, "NAST_UNKNOWN_OPT")) + return NAST_UNKNOWN_OPT; + else if (strEQ(name, "NAST_SERVER_ERR")) + return NAST_SERVER_ERR; + break; + case 'B': + break; + case 'C': + break; + case 'D': + break; + case 'E': + break; + case 'F': + break; + case 'G': + break; + case 'H': + break; + case 'I': + break; + case 'J': + break; + case 'K': + break; + case 'L': + break; + case 'M': + break; + case 'N': + break; + case 'O': + break; + case 'P': + break; + case 'Q': + break; + case 'R': + break; + case 'S': + break; + case 'T': + break; + case 'U': + break; + case 'V': + break; + case 'W': + break; + case 'X': + break; + case 'Y': + break; + case 'Z': + break; + } + errno = EINVAL; + return 0; + +not_there: + errno = ENOENT; + return 0; +} + + +MODULE = NASTD PACKAGE = NASTD + +PROTOTYPES: ENABLE + +double +constant(name,arg) + char * name + int arg + +nasth * +nast_sphincter_new(...) + PREINIT: + STRLEN n_a; + + CODE: + nasth *sphincter; + + if (items == 0) + sphincter = nast_sphincter_new(SvPV(ST(0), n_a)); + else + sphincter = nast_sphincter_new(NULL); + + if (sphincter == NULL) + XSRETURN_UNDEF; + + RETVAL = sphincter; + + OUTPUT: + RETVAL + +void +nast_sphincter_close(sphincter) + nasth *sphincter + +int +nast_options_get(sphincter) + nasth *sphincter + + PREINIT: + nast_options nast_opts; + + PPCODE: + if (nast_options_get(sphincter, &nast_opts) != -1) { + if (nast_opts.use_qcache == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + if (nast_opts.use_localdb == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + if (nast_opts.fallthrough_async == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + if (nast_opts.always_fallthrough == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + if (nast_opts.fail_once == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + if (nast_opts.no_fallthrough == NASTFALSE) + XPUSHs(sv_2mortal(newSViv(0))); + else + XPUSHs(sv_2mortal(newSViv(1))); + } + +int +nast_options_set(sphincter, ...) + nasth *sphincter + + PREINIT: + nast_options nast_opts; + int i; + + CODE: + if (items == 8) { + if (SvTRUE(ST(1))) + nast_opts.use_qcache = NASTTRUE; + else + nast_opts.use_qcache = NASTFALSE; + if (SvTRUE(ST(2))) + nast_opts.use_localdb = NASTTRUE; + else + nast_opts.use_localdb = NASTFALSE; + if (SvTRUE(ST(3))) + nast_opts.fallthrough_async = NASTTRUE; + else + nast_opts.fallthrough_async = NASTFALSE; + if (SvTRUE(ST(4))) + nast_opts.always_fallthrough = NASTTRUE; + else + nast_opts.always_fallthrough = NASTFALSE; + if (SvTRUE(ST(5))) + nast_opts.fail_once = NASTTRUE; + else + nast_opts.fail_once = NASTFALSE; + if (SvTRUE(ST(6))) + nast_opts.no_fallthrough = NASTTRUE; + else + nast_opts.no_fallthrough = NASTFALSE; + + RETVAL = nast_options_set(sphincter, &nast_opts); + } else + RETVAL = -1; + + OUTPUT: + RETVAL + +SV * +nast_get_result(sphincter) + nasth *sphincter + + PREINIT: + nast_array *aa; + int i; + + PPCODE: + aa = nast_get_result(sphincter); + if (aa != NULL) { + EXTEND(SP, aa->nitems); + + for (i = 0; i < aa->nitems; i++) { + SV *item; + + item = newSVpv(aa->items[i]->strdata, + aa->items[i]->strlen); + PUSHs(sv_2mortal(item)); + } + nast_free_result(aa); + } + +int +interface_nast_qcmd(sphincter, key) + nasth *sphincter + const char *key +INTERFACE: + nast_add nast_del nast_get + +int +nast_upd(sphincter, key, ...) + nasth *sphincter + const char *key + + PREINIT: + nast_array *aa; + int i; + + CODE: + aa = nast_array_new(); + if (aa != NULL) { + for (i = 2; i < items; i++) { + char *str; + STRLEN len; + + str = (char *)SvPV(ST(i), len); + nast_array_add(aa, len, str); + } + RETVAL = nast_upd(sphincter, key, aa); + } else { + RETVAL = -1; + } + nast_array_delete(aa); + + OUTPUT: + RETVAL + +int +nast_geterr(sphincter) + nasth *sphincter + +char * +nast_errmsg(sphincter) + nasth *sphincter + +int +nast_stats(sphincter) + nasth *sphincter diff --git a/perl/build b/perl/build new file mode 100755 index 0000000..123a249 --- /dev/null +++ b/perl/build @@ -0,0 +1,28 @@ +#!/bin/sh +# +# $Id: build,v 1.2 2000/05/16 19:27:05 shmit Exp $ + +if [ $# -lt 2 ]; then + echo "Usage: $0 makecmd perlflag args" 2>&1 + exit 1 +fi + +# Grab the make command +make=$1 && shift 1 + +# Should perl support be built? +perlflag=$1 && shift 1 + +if [ x"$perlflag" != x"YES" ]; then + echo "Perl support not enabled. Edit Makefiles/config to enable it." + exit 0 +fi + +if [ \! -f Makefile ]; then + # + # Build the Makefile + # + /usr/bin/env perl Makefile.PL +fi + +$make MAKE=$make $* diff --git a/perl/include/.svn/README.txt b/perl/include/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/perl/include/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/perl/include/.svn/empty-file b/perl/include/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/perl/include/.svn/empty-file diff --git a/perl/include/.svn/entries b/perl/include/.svn/entries new file mode 100644 index 0000000..b9bcaeb --- /dev/null +++ b/perl/include/.svn/entries @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk/perl/include" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + committed-rev="1" + name="nastdxs.def" + text-time="2005-12-24T00:00:42.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="47d3ee470643494f1e8635910003c9aa" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:42.000000Z"/> +</wc-entries> diff --git a/perl/include/.svn/format b/perl/include/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/perl/include/.svn/format @@ -0,0 +1 @@ +4 diff --git a/perl/include/.svn/prop-base/nastdxs.def.svn-base b/perl/include/.svn/prop-base/nastdxs.def.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/include/.svn/prop-base/nastdxs.def.svn-base @@ -0,0 +1 @@ +END diff --git a/perl/include/.svn/props/nastdxs.def.svn-work b/perl/include/.svn/props/nastdxs.def.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/perl/include/.svn/props/nastdxs.def.svn-work @@ -0,0 +1 @@ +END diff --git a/perl/include/.svn/text-base/nastdxs.def.svn-base b/perl/include/.svn/text-base/nastdxs.def.svn-base new file mode 100644 index 0000000..70f6c7b --- /dev/null +++ b/perl/include/.svn/text-base/nastdxs.def.svn-base @@ -0,0 +1,10 @@ +#ifndef NASTDXS_DEF +#define NASTDXS_DEF + +struct _nasth { + nasth *s; +}; + +typedef struct _nasth * NASTD__Hole; + +#endif diff --git a/perl/include/nastdxs.def b/perl/include/nastdxs.def new file mode 100644 index 0000000..70f6c7b --- /dev/null +++ b/perl/include/nastdxs.def @@ -0,0 +1,10 @@ +#ifndef NASTDXS_DEF +#define NASTDXS_DEF + +struct _nasth { + nasth *s; +}; + +typedef struct _nasth * NASTD__Hole; + +#endif diff --git a/perl/pm_to_blib b/perl/pm_to_blib new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/perl/pm_to_blib diff --git a/perl/test.pl b/perl/test.pl new file mode 100644 index 0000000..6a12cbf --- /dev/null +++ b/perl/test.pl @@ -0,0 +1,111 @@ +# $Id: test.pl,v 1.20 2001/03/23 00:06:09 shmit Exp $ +# +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +######################### We start with some black magic to print on failure. + +# Change 1..1 below to 1..last_test_to_print . +# (It may become useful if the test is moved to ./t subdirectory.) + +BEGIN { $| = 1; print "1..8\n"; } +END {print "not ok 1\n" unless $loaded;} +use NASTD; +$loaded = 1; +print "ok 1\n"; + +######################### End of black magic. + +# Insert your test code below (better if it prints "ok 13" +# (correspondingly "not ok 13") depending on the success of chunk 13 +# of the test code): + +$nasthole = &NASTD::nast_sphincter_new(); +if (!defined($nasthole)) { + print "not ok 2\n"; +} else { + print "ok 2\n"; +} + +# +# Set options +# +@setopts = (1, 1, 0, 0, 0, 1, 5); +if (&NASTD::nast_options_set($nasthole, @setopts) == -1) { + print "not ok 3\n"; +} else { + print "ok 3\n"; +} + +# +# Check options +# +@optarr = &NASTD::nast_options_get($nasthole); +$nitems = $#optarr + 1; +for ($i = 0; $i < $nitems; $i++) { + if ($optarr[$i] != $setopts[$i]) { + print "not ok 4\n"; + last; + } +} +if ($i == $nitems) { + print "ok 4\n"; +} + +# +# Perform get +# +$rv = &NASTD::nast_get($nasthole, "shmit"); +if ($rv == -1) { + print "not ok 5\n"; +} else { + print "ok 5\n"; +} + +# +# Perform update +# +@vals = ("foo", "bar", "baz"); + +$rv = &NASTD::nast_upd($nasthole, "shmit", @vals); +if ($rv == -1) { + print "not ok 6\n"; +} else { + print "ok 6\n"; +} + +# +# Verify update +# +$rv = &NASTD::nast_get($nasthole, "shmit"); +if ($rv == -1) { + print "not ok 7\n"; +} else { + print "ok 7\n"; +} + +$rv = &NASTD::nast_geterr($nasthole); +if ($rv != 0) { + print "not ok 8\n"; +} else { + print "ok 8\n"; +} + +# +# Close the sphincter when we don't need it anymore. +# +&NASTD::nast_sphincter_close($nasthole); + +# +# This grabs the results and prints them. +# +sub print_results +{ + my @vals = &NASTD::nast_get_result($nasthole); + + my $nitems = $#vals + 1; + for ($i = 0; $i < $nitems; $i++) { + my $foo = shift(@vals); + print "Result[$i]: $foo\n"; + } +} diff --git a/perl/test_fallthrough b/perl/test_fallthrough new file mode 100755 index 0000000..50feed8 --- /dev/null +++ b/perl/test_fallthrough @@ -0,0 +1,38 @@ +#!/usr/bin/perl + +use NASTD; + +$nasthole = &NASTD::nast_sphincter_new(); +if (!defined($nasthole)) { + exit(1); +} + +@options = &NASTD::nast_options_get($nasthole); +if (!defined(@options)) { + print STDERR "Couldn't get options: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + exit(1); +} + +$options[5] = 1; +if (&NASTD::nast_options_set($nasthole, @options) == -1) { + print STDERR "Couldn't set options: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + exit(1); +} + +if (&NASTD::nast_get($nasthole, "asljkda") == -1) { + print STDERR "Couldn't perform get: " . + &NASTD::nast_errmsg($nasthole) . "\n"; + exit(1); +} + +@vals = &NASTD::nast_get_result($nasthole); +$nitems = $#vals + 1; +print "Number of columns: " . $nitems . "\n"; +for ($i = 0; $i < $nitems; $i++) { + $val = shift(@vals); + print "Result[$i]: $val\n"; +} + +&NASTD::nast_sphincter_close($nasthole); diff --git a/perl/typemap b/perl/typemap new file mode 100644 index 0000000..c22830d --- /dev/null +++ b/perl/typemap @@ -0,0 +1,23 @@ +const char * T_PV +nasth * T_PTROBJ +NASTD::Hole O_NASTH + +# +# Output methods +# +OUTPUT +O_NASTH + sv_setref_pv($arg, "Asshole", (void *)$var); + +# +# Input methods +# +INPUT +O_NASTH + if (sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG)) { + $var = ($type)SvIV((SV *)SvRV($arg)); + } else { + warn(\"${Package}::$func_name() --\" + \" $var is not a valid nasthole.\"); + XSRETURN_UNDEF; + } diff --git a/server/.cvsignore b/server/.cvsignore new file mode 100644 index 0000000..c656c21 --- /dev/null +++ b/server/.cvsignore @@ -0,0 +1,8 @@ +nastd +.pure +*.o +*.so +*.a +*.core +*.gmon +tags diff --git a/server/.pure b/server/.pure new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/server/.pure diff --git a/server/.svn/README.txt b/server/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/server/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/server/.svn/empty-file b/server/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/server/.svn/empty-file diff --git a/server/.svn/entries b/server/.svn/entries new file mode 100644 index 0000000..75a456a --- /dev/null +++ b/server/.svn/entries @@ -0,0 +1,265 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk/server" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + committed-rev="1" + name="periodic.c" + text-time="2005-12-24T00:00:52.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="9ab6f8fb29a2ab22ad6c371b670aaa78" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:49.000000Z"/> +<entry + committed-rev="1" + name="cdbpriv.h" + text-time="2005-12-24T00:00:52.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="b04ca2fe0d69d678bbd954d5ca1046c6" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:49.000000Z"/> +<entry + committed-rev="1" + name="nastdio.c" + text-time="2005-12-24T00:00:52.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="14fde9ce0366ccada683bc6bfad47a03" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:49.000000Z"/> +<entry + committed-rev="1" + name="periodic.h" + text-time="2005-12-24T00:00:53.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="aa6705635a8d4265cbd6348823b538c2" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:49.000000Z"/> +<entry + committed-rev="1" + name="nastdio.h" + text-time="2005-12-24T00:00:53.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="9df20501cc13a633b8c393c72649546d" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:49.000000Z"/> +<entry + committed-rev="1" + name="thread.c" + text-time="2005-12-24T00:00:53.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="4cd24cd9f6877f80b7921efdfb03751c" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:50.000000Z"/> +<entry + committed-rev="1" + name=".pure" + text-time="2005-12-24T00:00:53.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="d41d8cd98f00b204e9800998ecf8427e" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:50.000000Z"/> +<entry + committed-rev="1" + name="nastd.c" + text-time="2005-12-24T00:00:53.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="d09727d31e0c616e3b50f138a98a7c6f" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:50.000000Z"/> +<entry + committed-rev="1" + name="mysqldb.c" + text-time="2005-12-24T00:00:53.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="9c95871bbe8737d0ea68f0a4fac84629" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:50.000000Z"/> +<entry + committed-rev="1" + name="thread.h" + text-time="2005-12-24T00:00:53.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="f50e611ab3f72f79ad5d952781376665" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:50.000000Z"/> +<entry + committed-rev="1" + name="array.c" + text-time="2005-12-24T00:00:53.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="b517ceff3a424b967e6d38e8b325b6aa" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:50.000000Z"/> +<entry + committed-rev="1" + name="mysqldb.h" + text-time="2005-12-24T00:00:53.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="f9765376cccfa9f80c82f7a7b5c747c6" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:50.000000Z"/> +<entry + committed-rev="1" + name="log.c" + text-time="2005-12-24T00:00:53.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="ae49c6ca92752738c2a0f6dd81666817" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:50.000000Z"/> +<entry + committed-rev="1" + name="array.h" + text-time="2005-12-24T00:00:54.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="9ad3ee2195e9917b98173825d0ddf53a" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:51.000000Z"/> +<entry + committed-rev="1" + name="fqm.c" + text-time="2005-12-24T00:00:53.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="e5f212af7ef0ce67764a5017f22c43af" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:50.000000Z"/> +<entry + committed-rev="1" + name="memdb.c" + text-time="2005-12-24T00:00:54.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="b82f28b318f365f9b9289328a21aef76" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:51.000000Z"/> +<entry + committed-rev="1" + name="md5.c" + text-time="2005-12-24T00:00:54.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="8e1191d8f06f198585e0c025232a5411" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:51.000000Z"/> +<entry + committed-rev="1" + name="log.h" + text-time="2005-12-24T00:00:54.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="1acee0ec3cf339b45df070838a7229c1" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:51.000000Z"/> +<entry + committed-rev="1" + name="fqm.h" + text-time="2005-12-24T00:00:54.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="1b4fc62462465934914fcf7614cb37b1" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:51.000000Z"/> +<entry + committed-rev="1" + name="cdb_find.c" + text-time="2005-12-24T00:00:54.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="8b7a134f62e6b2ca0823a26b9e055358" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:51.000000Z"/> +<entry + committed-rev="1" + name="cdb.c" + text-time="2005-12-24T00:00:54.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="6ae6b86a75220cd0334cd23b8ffbf8fd" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:51.000000Z"/> +<entry + committed-rev="1" + name="cdb_unpack.c" + text-time="2005-12-24T00:00:54.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="72a688b528b8ec040f755a6a24f48f23" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:51.000000Z"/> +<entry + committed-rev="1" + name="memdb.h" + text-time="2005-12-24T00:00:54.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="6312c1468cf623288611a981e173ef5f" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:52.000000Z"/> +<entry + committed-rev="1" + name="md5.h" + text-time="2005-12-24T00:00:54.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="c6837ec020c3d9e7c2792b2a114853fe" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:52.000000Z"/> +<entry + committed-rev="1" + name="cdb_hash.c" + text-time="2005-12-24T00:00:55.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="2f63db3059a51e03db8d2b6502edaf0a" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:52.000000Z"/> +<entry + committed-rev="1" + name="Makefile" + text-time="2005-12-24T00:00:55.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="fe3c112570d1215c4b5aafe76042f53c" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:52.000000Z"/> +<entry + committed-rev="1" + name=".cvsignore" + text-time="2005-12-24T00:00:55.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="b3345144ac86fa19fdfc3f4845fded00" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:52.000000Z"/> +<entry + committed-rev="1" + name="cdb.h" + text-time="2005-12-24T00:00:55.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="bea51b513470729ab998b007e2ea760f" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:52.000000Z"/> +</wc-entries> diff --git a/server/.svn/format b/server/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/server/.svn/format @@ -0,0 +1 @@ +4 diff --git a/server/.svn/prop-base/.cvsignore.svn-base b/server/.svn/prop-base/.cvsignore.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/.cvsignore.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/.pure.svn-base b/server/.svn/prop-base/.pure.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/.pure.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/Makefile.svn-base b/server/.svn/prop-base/Makefile.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/Makefile.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/array.c.svn-base b/server/.svn/prop-base/array.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/array.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/array.h.svn-base b/server/.svn/prop-base/array.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/array.h.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/cdb.c.svn-base b/server/.svn/prop-base/cdb.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/cdb.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/cdb.h.svn-base b/server/.svn/prop-base/cdb.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/cdb.h.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/cdb_find.c.svn-base b/server/.svn/prop-base/cdb_find.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/cdb_find.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/cdb_hash.c.svn-base b/server/.svn/prop-base/cdb_hash.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/cdb_hash.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/cdb_unpack.c.svn-base b/server/.svn/prop-base/cdb_unpack.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/cdb_unpack.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/cdbpriv.h.svn-base b/server/.svn/prop-base/cdbpriv.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/cdbpriv.h.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/fqm.c.svn-base b/server/.svn/prop-base/fqm.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/fqm.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/fqm.h.svn-base b/server/.svn/prop-base/fqm.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/fqm.h.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/log.c.svn-base b/server/.svn/prop-base/log.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/log.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/log.h.svn-base b/server/.svn/prop-base/log.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/log.h.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/md5.c.svn-base b/server/.svn/prop-base/md5.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/md5.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/md5.h.svn-base b/server/.svn/prop-base/md5.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/md5.h.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/memdb.c.svn-base b/server/.svn/prop-base/memdb.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/memdb.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/memdb.h.svn-base b/server/.svn/prop-base/memdb.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/memdb.h.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/mysqldb.c.svn-base b/server/.svn/prop-base/mysqldb.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/mysqldb.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/mysqldb.h.svn-base b/server/.svn/prop-base/mysqldb.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/mysqldb.h.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/nastd.c.svn-base b/server/.svn/prop-base/nastd.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/nastd.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/nastdio.c.svn-base b/server/.svn/prop-base/nastdio.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/nastdio.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/nastdio.h.svn-base b/server/.svn/prop-base/nastdio.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/nastdio.h.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/periodic.c.svn-base b/server/.svn/prop-base/periodic.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/periodic.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/periodic.h.svn-base b/server/.svn/prop-base/periodic.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/periodic.h.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/thread.c.svn-base b/server/.svn/prop-base/thread.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/thread.c.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/prop-base/thread.h.svn-base b/server/.svn/prop-base/thread.h.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/prop-base/thread.h.svn-base @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/.cvsignore.svn-work b/server/.svn/props/.cvsignore.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/.cvsignore.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/.pure.svn-work b/server/.svn/props/.pure.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/.pure.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/Makefile.svn-work b/server/.svn/props/Makefile.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/Makefile.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/array.c.svn-work b/server/.svn/props/array.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/array.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/array.h.svn-work b/server/.svn/props/array.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/array.h.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/cdb.c.svn-work b/server/.svn/props/cdb.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/cdb.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/cdb.h.svn-work b/server/.svn/props/cdb.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/cdb.h.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/cdb_find.c.svn-work b/server/.svn/props/cdb_find.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/cdb_find.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/cdb_hash.c.svn-work b/server/.svn/props/cdb_hash.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/cdb_hash.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/cdb_unpack.c.svn-work b/server/.svn/props/cdb_unpack.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/cdb_unpack.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/cdbpriv.h.svn-work b/server/.svn/props/cdbpriv.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/cdbpriv.h.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/fqm.c.svn-work b/server/.svn/props/fqm.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/fqm.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/fqm.h.svn-work b/server/.svn/props/fqm.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/fqm.h.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/log.c.svn-work b/server/.svn/props/log.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/log.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/log.h.svn-work b/server/.svn/props/log.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/log.h.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/md5.c.svn-work b/server/.svn/props/md5.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/md5.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/md5.h.svn-work b/server/.svn/props/md5.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/md5.h.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/memdb.c.svn-work b/server/.svn/props/memdb.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/memdb.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/memdb.h.svn-work b/server/.svn/props/memdb.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/memdb.h.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/mysqldb.c.svn-work b/server/.svn/props/mysqldb.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/mysqldb.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/mysqldb.h.svn-work b/server/.svn/props/mysqldb.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/mysqldb.h.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/nastd.c.svn-work b/server/.svn/props/nastd.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/nastd.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/nastdio.c.svn-work b/server/.svn/props/nastdio.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/nastdio.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/nastdio.h.svn-work b/server/.svn/props/nastdio.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/nastdio.h.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/periodic.c.svn-work b/server/.svn/props/periodic.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/periodic.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/periodic.h.svn-work b/server/.svn/props/periodic.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/periodic.h.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/thread.c.svn-work b/server/.svn/props/thread.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/thread.c.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/props/thread.h.svn-work b/server/.svn/props/thread.h.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/server/.svn/props/thread.h.svn-work @@ -0,0 +1 @@ +END diff --git a/server/.svn/text-base/.cvsignore.svn-base b/server/.svn/text-base/.cvsignore.svn-base new file mode 100644 index 0000000..c656c21 --- /dev/null +++ b/server/.svn/text-base/.cvsignore.svn-base @@ -0,0 +1,8 @@ +nastd +.pure +*.o +*.so +*.a +*.core +*.gmon +tags diff --git a/server/.svn/text-base/.pure.svn-base b/server/.svn/text-base/.pure.svn-base new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/server/.svn/text-base/.pure.svn-base diff --git a/server/.svn/text-base/Makefile.svn-base b/server/.svn/text-base/Makefile.svn-base new file mode 100644 index 0000000..0d26efe --- /dev/null +++ b/server/.svn/text-base/Makefile.svn-base @@ -0,0 +1,32 @@ +# $Id: Makefile,v 1.17 2001/10/04 23:57:09 shmit Exp $ + +OBJS= array.o nastd.o nastdio.o cdb.o cdb_find.o cdb_hash.o \ + cdb_unpack.o fqm.o log.o md5.o memdb.o mysqldb.o periodic.o \ + thread.o ../libconfig/libconfig.a + +nastd: ${OBJS} + ${PURIFY} ${CC} -o $@ ${OBJS} ${LIBS} ${MYSQL_LIBS} + +# +# Dependencies +# +array.o: array.h log.h +nastd.o: ../include/nastipc.h ../include/config.h nastdio.h \ + cdb.h log.h memdb.h mysqldb.h periodic.h +nastdio.o: ../include/nastd.h ../include/nastipc.h array.h \ + nastdio.h cdb.h fqm.h log.h memdb.h mysqldb.h thread.h +cdb.o: ../include/config.h array.h nastdio.h cdbpriv.h log.h \ + memdb.h thread.h +cdb_find.o: cdbpriv.h +cdb_hash.o: cdbpriv.h +cdb_unpack.o: cdbpriv.h +fqm.o: fqm.h log.h thread.h +log.o: log.h +md5.o: log.h md5.h +memdb.o: ../include/config.h array.h log.h md5.h memdb.h thread.h +mysqldb.o: array.h nastdio.h log.h mysqldb.h +periodic.o: cdb.h log.h thread.h periodic.h +thread.o: thread.h + +MKDIR= ../Makefiles +include ${MKDIR}/build diff --git a/server/.svn/text-base/array.c.svn-base b/server/.svn/text-base/array.c.svn-base new file mode 100644 index 0000000..65766de --- /dev/null +++ b/server/.svn/text-base/array.c.svn-base @@ -0,0 +1,149 @@ +#include "conf.h" +#include "array.h" +#include "log.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +RCSID("$Id: array.c,v 1.10 2000/10/17 23:38:27 shmit Exp $"); + +string_t * +string_new(int slen, char *strdata) +{ + string_t *tmp; + + tmp = malloc(sizeof(string_t)); + if (tmp == NULL) { + log_err("Couldn't allocate data for string: %s.", + strerror(errno)); + return NULL; + } + + tmp->str = malloc(slen * sizeof(char *)); + if (tmp->str == NULL) { + log_err("Couldn't allocate string data: %s.", + strerror(errno)); + return NULL; + } + memcpy(tmp->str, strdata, slen); + tmp->strlen = slen; + + return tmp; +} + +void +string_delete(string_t *string) +{ + if (string == NULL) + return; + + if (string->str != NULL) + free(string->str); + string->strlen = 0; + string->str = NULL; + free(string); +} + +array_t * +array_new() +{ + array_t *tmp; + + tmp = malloc(sizeof(array_t)); + if (tmp == NULL) + return NULL; + + tmp->nitems = 0; + tmp->items = NULL; + return tmp; +} + +void +array_delete(array_t *aa) +{ + int i; + + if (aa == NULL) + return; + + for (i = 0; i < aa->nitems; i++) + string_delete(aa->items[i]); + free(aa->items); + aa->items = NULL; + free(aa); +} + +int +va_array_add(array_t *aa, va_list ap) +{ + const int GRANULARITY = 10; + int slen; + char *s; + + slen = va_arg(ap, int); + if (slen != ARRTERM) + s = va_arg(ap, char *); + else + s = NULL; + while (s) { + if (aa->nitems % GRANULARITY == 0) { + aa->items = realloc(aa->items, sizeof(string_t *) * + (GRANULARITY + aa->nitems)); + if (aa->items == NULL) + return -1; + } + aa->nitems++; + aa->items[aa->nitems-1] = string_new(slen, s); + if (aa->items[aa->nitems-1] == NULL) + return -1; + slen = va_arg(ap, int); + if (slen != ARRTERM) + s = va_arg(ap, char *); + else + s = NULL; + } + + return 0; +} + +int +array_add(array_t *aa, ...) +{ + va_list ap; + int rc; + + va_start(ap, aa); + rc = va_array_add(aa, ap); + va_end(ap); + + return rc; +} + +int +array_dup(array_t *dst, array_t *src) +{ + int i; + + if (dst == NULL) + return -1; + + dst->nitems = src->nitems; + dst->items = malloc(dst->nitems * sizeof(string_t *)); + if (dst->items == NULL) { + log_err("Couldn't allocate dup array items list: %s.", + strerror(errno)); + return -1; + } + + for (i = 0; i < dst->nitems; i++) { + dst->items[i] = string_new(src->items[i]->strlen, + src->items[i]->str); + if (dst->items[i] == NULL) { + dst->nitems = i; + return -1; + } + } + + return 0; +} diff --git a/server/.svn/text-base/array.h.svn-base b/server/.svn/text-base/array.h.svn-base new file mode 100644 index 0000000..83b4ee1 --- /dev/null +++ b/server/.svn/text-base/array.h.svn-base @@ -0,0 +1,31 @@ +/* $Id: array.h,v 1.4 2000/10/17 23:38:27 shmit Exp $ */ + +#ifndef ARRAY_H +#define ARRAY_H + +#include <stdarg.h> + +#define ARRTERM -1 + +struct _string_t { + char *str; + int strlen; +}; +typedef struct _string_t string_t; + +struct _array_t { + int nitems; + string_t **items; +}; +typedef struct _array_t array_t; + +string_t *string_new(int slen, char *strdata); +void string_delete(string_t *string); + +array_t *array_new(); +void array_delete(array_t *array); +int va_array_add(array_t *aa, va_list ap); +int array_add(array_t *aa, ...); +int array_dup(array_t *dst, array_t *src); + +#endif diff --git a/server/.svn/text-base/cdb.c.svn-base b/server/.svn/text-base/cdb.c.svn-base new file mode 100644 index 0000000..4f55d03 --- /dev/null +++ b/server/.svn/text-base/cdb.c.svn-base @@ -0,0 +1,324 @@ +#include "conf.h" +#include "config.h" +#include "array.h" +#include "nastdio.h" +#include "cdbpriv.h" +#include "log.h" +#include "memdb.h" +#include "thread.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> + +RCSID("$Id: cdb.c,v 1.64 2001/10/19 22:28:07 shmit Exp $"); + +time_t cdb_mtime; + +static char *memcdb = NULL; +static rw_mutex_t *cdb_lk = NULL; +static uint32_t cdb_len = 0; + +/* + * Exportable symbols - the CDB file is authoritative for them, so they + * come from here, but nastdio.c is their consumer. + */ +char db_key[1024]; +char db_dbn[1024]; +char db_tbl[1024]; +fieldent *db_fields = NULL; +char db_sep; +short db_fieldcount = 0; + +static int sec_c; +static float onemin_c, fivemin_c, fifteenmin_c; + +static int +cdb_findbykey(char *mcdb, int len, const char *key, int keylen, + char **data, int *dlen) +{ + if (cdb_find(mcdb, len, key, keylen, data, dlen) != 1) + return -1; + + return 0; +} + +int +cdb_new() +{ + char *newcdb; + char *p, *s_p, *e_p; + fieldent *newfields; + char buffer[1024]; + char cdbfields_s[1024], newkey[1024], newtbl[1024], newdbn[1024]; + char newsep; + struct stat sb; + int i, fieldslen, newfieldcount; + int fd; + size_t len; + + log_info("Initialising CDB interface."); + + sec_c = 0; + onemin_c = fivemin_c = fifteenmin_c = 0; + + if (!cdb_lk) { + cdb_lk = malloc(sizeof(rw_mutex_t)); + if (!cdb_lk) { + log_err("Couldn't allocate CDB mutex: %s.", + strerror(errno)); + return -1; + } + if (rw_mutex_new(cdb_lk)) { + log_err("Couldn't initialse CDB mutex: %s.", + strerror(errno)); + return -1; + } + } + + snprintf(buffer, sizeof(buffer), "%s/%s", + config.nast_dir, config.nast_cdb_file); + fd = open(buffer, O_RDONLY); + if (fd == -1) { + log_err("Couldn't open %s: %s.", buffer, strerror(errno)); + return -1; + } + + if (fstat(fd, &sb) == -1) { + log_err("Couldn't stat %s: %s.", buffer, strerror(errno)); + return -1; + } + len = sb.st_size; + + newcdb = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); + if (newcdb == MAP_FAILED) { + log_err("Couldn't mmap %s: %s.", buffer, strerror(errno)); + return -1; + } + + (void)close(fd); + + /* Get the key out of the CDB, so clients know how to search. */ + if (cdb_findbykey(newcdb, len, "_KEY_", strlen("_KEY_"), + &p, &i) == -1) { + log_err("Couldn't find `_KEY_' in the CDB."); + munmap(newcdb, len); + return -1; + } + + if (i > sizeof(newkey)) { + log_err("Couldn't copy key information from the CDB."); + munmap(newcdb, len); + return -1; + } + memcpy(newkey, p, i); + newkey[i] = '\0'; + + /* Get the dbname out of the CDB, so mysql knows which db to use. */ + if (cdb_findbykey(newcdb, len, "_DB_", strlen("_DB_"), &p, &i) == -1) { + log_err("Warning: Couldn't find `_DB_' in the CDB."); + strncpy(newdbn, DBNAME, sizeof(newdbn)); + } else { + if (i > sizeof(newdbn)) { + log_err("Couldn't copy database information " + "from the CDB."); + munmap(newcdb, len); + return -1; + } + memcpy(newdbn, p, i); + newdbn[i] = '\0'; + } + + /* Get the table out of the CDB, so mysql knows which to use. */ + if (cdb_findbykey(newcdb, len, "_TABLE_", strlen("_TABLE_"), + &p, &i) == -1) { + log_err("Warning: Couldn't find `_TABLE_' in the CDB."); + strncpy(newtbl, DBTBL, sizeof(newtbl)); + } else { + if (i > sizeof(newtbl)) { + log_err("Couldn't copy table information " + "from the CDB."); + munmap(newcdb, len); + return -1; + } + memcpy(newtbl, p, i); + newtbl[i] = '\0'; + } + + /* Get the delimiter out of the CDB file. */ + if (cdb_findbykey(newcdb, len, "_DELIM_", strlen("_DELIM_"), + &p, &i) == -1) { + log_info("Couldn't find `_DELIM_' in the CDB. Using default."); + newsep = ':'; + } else + newsep = *p; + + /* Now get the column names. */ + if (cdb_findbykey(newcdb, len, "_VALUES_", strlen("_VALUES_"), + &p, &i) == -1) { + log_err("Couldn't find `_VALUES_' in the CDB."); + munmap(newcdb, len); + return -1; + } + if (i >= sizeof(cdbfields_s)) { + log_err("Couldn't copy value information from the CDB."); + munmap(newcdb, len); + return -1; + } + memcpy(cdbfields_s, p, i); + cdbfields_s[i] = '\0'; + fieldslen = strlen(cdbfields_s); + + /* Fill out cdbfields with an array of field names. */ + newfieldcount = 0; + for (i = 0; i <= fieldslen; i++) { + if (cdbfields_s[i] == newsep || i == fieldslen) + newfieldcount++; + } + + newfields = malloc(sizeof(fieldent) * newfieldcount); + if (newfields == NULL) { + log_err("Couldn't allocate space for field array: %s.", + strerror(errno)); + munmap(newcdb, len); + return -1; + } + + s_p = cdbfields_s; + for (i = 0; i < newfieldcount; i++) { + for (e_p = s_p; *e_p != newsep && *e_p != '\0'; e_p++); + + newfields[i].index = i; + newfields[i].name = malloc(e_p - s_p + 1*sizeof(char)); + if (newfields[i].name == NULL) { + /* XXX: clean up. */ + log_err("Couldn't allocate space for field: %s.", + strerror(errno)); + munmap(newcdb, len); + return -1; + } + memcpy(newfields[i].name, s_p, e_p - s_p); + newfields[i].name[e_p - s_p] = '\0'; + s_p = e_p + 1; + } + + rw_mutex_write_lock(cdb_lk); + if (memcdb) + munmap(memcdb, cdb_len); + memcdb = newcdb; + cdb_len = (uint32_t)len; + cdb_mtime = sb.st_mtime; + + memcpy(db_dbn, newdbn, sizeof(db_dbn)); + memcpy(db_tbl, newtbl, sizeof(db_tbl)); + memcpy(db_key, newkey, sizeof(db_key)); + if (db_fields) + free(db_fields); + db_fields = newfields; + db_sep = newsep; + db_fieldcount = newfieldcount; + rw_mutex_unlock(cdb_lk); + + log_info("CDB interface initialised."); + return 0; +} + +int +cdb_get(const char *key, int keylen, array_t *aa) +{ + char *s_p, *e_p; + char *data; + int dlen; + + rw_mutex_read_lock(cdb_lk); + if (cdb_findbykey(memcdb, cdb_len, key, keylen, &data, &dlen) == -1) { + rw_mutex_unlock(cdb_lk); + return -1; + } + + sec_c++; + + s_p = data; e_p = data; + while (e_p <= data+dlen) { + if (*e_p == db_sep || e_p == data+dlen) { + if (array_add(aa, e_p-s_p, s_p, ARRTERM) == -1) { + rw_mutex_unlock(cdb_lk); + return -1; + } + s_p = e_p + 1; + } + e_p++; + } + + rw_mutex_unlock(cdb_lk); + return 0; +} + +void +cdb_periodic() +{ + char buffer[1024]; + struct stat sb; + + snprintf(buffer, sizeof(buffer), "%s/%s", + config.nast_dir, config.nast_cdb_file); + if (stat(buffer, &sb) == -1) { + log_err("PERIODIC: Couldn't stat %s: %s.\n", buffer, + strerror(errno)); + return; + } + + if (sb.st_size == 0) { + log_err("PERIODIC: WARNING! CDB file is empty!"); + return; + } + + if (cdb_mtime < sb.st_mtime) { + log_info("PERIODIC: CDB file changed, reloading.\n"); + (void)cdb_new(); + + /* + * Turned off, as now entries are time stamped and + * auto-expire when the cdb file is updated. + */ + /* (void)memdb_new(); */ + return; + } +} + +int +cdb_stats(array_t *statarr) +{ + char buffer[512]; + char tbuff[512]; + struct tm res; + + snprintf(buffer, sizeof(buffer), "CDB: %.2f, %.2f, %.2f", + onemin_c, fivemin_c, fifteenmin_c); + if (array_add(statarr, strlen(buffer), buffer, ARRTERM) == -1) + return -1; + + /* Convert CDB mtime into a string. */ + (void)localtime_r(&cdb_mtime, &res); + strftime(tbuff, sizeof(tbuff), "%Y%m%d %H:%M:%S", &res); + + snprintf(buffer, sizeof(buffer), "CDB: last updated: %s", + tbuff); + return array_add(statarr, strlen(buffer), buffer, ARRTERM); +} + +void +cdb_collate() +{ + onemin_c = ((onemin_c * 59) + sec_c) / 60; + fivemin_c = ((fivemin_c * 299) + sec_c) / 300; + fifteenmin_c = ((fifteenmin_c * 899) + sec_c) / 900; + sec_c = 0; +} diff --git a/server/.svn/text-base/cdb.h.svn-base b/server/.svn/text-base/cdb.h.svn-base new file mode 100644 index 0000000..0da14df --- /dev/null +++ b/server/.svn/text-base/cdb.h.svn-base @@ -0,0 +1,15 @@ +/* $Id: cdb.h,v 1.11 2000/05/17 19:32:58 shmit Exp $ */ + +#ifndef CDB_H +#define CDB_H + +#include "array.h" + +int cdb_new(); +int cdb_get(const char *key, int keylen, array_t *dstarr); +void cdb_periodic(); + +int cdb_stats(array_t *statarr); +void cdb_collate(); + +#endif diff --git a/server/.svn/text-base/cdb_find.c.svn-base b/server/.svn/text-base/cdb_find.c.svn-base new file mode 100644 index 0000000..2fc2bcf --- /dev/null +++ b/server/.svn/text-base/cdb_find.c.svn-base @@ -0,0 +1,121 @@ +#include "cdbpriv.h" + +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +RCSID("$Id: cdb_find.c,v 1.2 2000/02/29 19:31:33 shmit Exp $"); + +static int +cdb_bread(char **ptr, char *endptr, char *buf, unsigned int len) +{ + if ((*ptr)+len > endptr) { + errno = EIO; + return -1; + } + + memcpy(buf, *ptr, len); + *ptr += len; + return 0; +} + +static int +match(char **ptr, char *endptr, const char *key, unsigned int len) +{ + char buf[32]; + int n; + int i; + + n = sizeof(buf); + if (n > len) + n = len; + + while (len > 0) { + if (cdb_bread(ptr, endptr, buf, n) == -1) + return -1; + + for (i = 0; i < n; ++i) + if (buf[i] != key[i]) + return 0; + key += n; + len -= n; + } + + return 1; +} + +int +cdb_find(char *buff, off_t bufflen, const char *key, int len, + char **ret, uint32_t *retlen) +{ + char *cur, *end; + char packbuf[8]; + uint32_t pos; + uint32_t h; + uint32_t lenhash; + uint32_t h2; + uint32_t loop; + uint32_t poskd; + + cur = buff; + end = buff + bufflen; + + h = cdb_hash(key, len); + + pos = 8 * (h & 255); + cur += pos; + if (cur > end) { + errno = EIO; + return -1; + } + + if (cdb_bread(&cur, end, packbuf, 8) == -1) + return -1; + + pos = cdb_unpack(packbuf); + lenhash = cdb_unpack(packbuf + 4); + + if (!lenhash) return 0; + h2 = (h >> 8) % lenhash; + + for (loop = 0; loop < lenhash; ++loop) { + cur = buff + (pos + 8 * h2); + if (cur > end) { + errno = EIO; + return -1; + } + if (cdb_bread(&cur, end, packbuf, 8) == -1) + return -1; + poskd = cdb_unpack(packbuf + 4); + if (!poskd) + return 0; + + if (cdb_unpack(packbuf) == h) { + cur = buff + poskd; + if (cur > end) { + errno = EIO; + return -1; + } + if (cdb_bread(&cur, end, packbuf, 8) == -1) + return -1; + if (cdb_unpack(packbuf) == len) { + switch(match(&cur, end, key, len)) { + case -1: + return -1; + case 1: + *retlen = cdb_unpack(&packbuf[4]); + *ret = cur; + return 1; + } + } + } + if (++h2 == lenhash) + h2 = 0; + } + + return 0; +} diff --git a/server/.svn/text-base/cdb_hash.c.svn-base b/server/.svn/text-base/cdb_hash.c.svn-base new file mode 100644 index 0000000..b664ba9 --- /dev/null +++ b/server/.svn/text-base/cdb_hash.c.svn-base @@ -0,0 +1,18 @@ +#include "conf.h" +#include "cdbpriv.h" + +RCSID("$Id: cdb_hash.c,v 1.2 2000/02/29 19:31:33 shmit Exp $"); + +uint32_t +cdb_hash(const unsigned char *buf, unsigned int len) +{ + uint32_t h; + + h = 5381; + while (len) { + --len; + h += (h << 5); + h ^= (uint32_t)*buf++; + } + return h; +} diff --git a/server/.svn/text-base/cdb_unpack.c.svn-base b/server/.svn/text-base/cdb_unpack.c.svn-base new file mode 100644 index 0000000..14a71b9 --- /dev/null +++ b/server/.svn/text-base/cdb_unpack.c.svn-base @@ -0,0 +1,16 @@ +#include "conf.h" +#include "cdbpriv.h" + +RCSID("$Id: cdb_unpack.c,v 1.2 2000/02/29 19:31:33 shmit Exp $"); + +uint32_t +cdb_unpack(unsigned char *buf) +{ + uint32_t num; + + num = buf[3]; num <<= 8; + num += buf[2]; num <<= 8; + num += buf[1]; num <<= 8; + num += buf[0]; + return num; +} diff --git a/server/.svn/text-base/cdbpriv.h.svn-base b/server/.svn/text-base/cdbpriv.h.svn-base new file mode 100644 index 0000000..cc398a8 --- /dev/null +++ b/server/.svn/text-base/cdbpriv.h.svn-base @@ -0,0 +1,15 @@ +/* $Id: cdbpriv.h,v 1.2 2000/02/29 19:15:28 shmit Exp $ */ + +#ifndef CDBPRIV_H +#define CDBPRIV_H + +#include "conf.h" + +#include <sys/types.h> + +int cdb_find(char *buff, off_t bufflen, const char *key, int len, + char **ret, uint32_t *retlen); +uint32_t cdb_hash(const unsigned char *buff, unsigned int len); +uint32_t cdb_unpack(unsigned char *buff); + +#endif diff --git a/server/.svn/text-base/fqm.c.svn-base b/server/.svn/text-base/fqm.c.svn-base new file mode 100644 index 0000000..73c9e54 --- /dev/null +++ b/server/.svn/text-base/fqm.c.svn-base @@ -0,0 +1,448 @@ +#include "conf.h" +#include "fqm.h" +#include "log.h" +#include "mysqldb.h" +#include "thread.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +RCSID("$Id: fqm.c,v 1.33 2001/10/29 11:17:13 shmit Exp $"); + +/* Global Variables */ +fqm_t *fqm; + +request_t * +req_new(int sock, short reqid, REQHANDLER((*req_handler)), + const char *reqstr, int reqlen) +{ + request_t *tmp; + + tmp = malloc(sizeof(request_t)); + if (tmp == NULL) { + log_err("Couldn't allocate request: %s.", strerror(errno)); + return NULL; + } + + tmp->req = malloc((reqlen + 1) * sizeof(char)); + if (tmp->req == NULL) { + log_err("Couldn't allocate request string: %s.", + strerror(errno)); + req_delete(tmp); + return NULL; + } + memcpy(tmp->req, reqstr, reqlen); + tmp->req[reqlen] = '\0'; + tmp->sock = sock; + tmp->reqid = reqid; + tmp->req_handler = req_handler; + + return tmp; +} + +void +req_delete(request_t *req) +{ + if (req) { + if (req->req) + free(req->req); + free(req); + } +} + +static request_t * +fqm_pop(reqthread_t *req) +{ + fqm_t *fqm; + request_t *p; + + if (req == NULL || req->fqm == NULL) { + mutex_unlock(&req->fqm->q_cond->lock); + return NULL; + } + fqm = req->fqm; + + /* Wait for something to arrive on the queue. */ + mutex_lock(&req->fqm->q_cond->lock); + req->status = IDLE; + + if (fqm->sreq == NULL) + cond_wait(fqm->q_cond); + + /* Something waiting on the queue. Scarf it off and unlock. */ + p = fqm->sreq; + if (p == NULL) { + mutex_unlock(&fqm->q_cond->lock); + return NULL; + } + fqm->sreq = fqm->sreq->next; + fqm->nitems--; + req->status = BUSY; + mutex_unlock(&fqm->q_cond->lock); + + p->next = NULL; + return p; +} + +static void * +fqm_popper(void *arg) +{ + reqthread_t *self; + request_t *req; + + /* Detach this thread. */ + (void)pthread_detach(pthread_self()); + + self = (reqthread_t *)arg; + for (;;) { + req = fqm_pop(self); + + /* + * Check to see if we were told to die. If we were, + * do so. + * Note: there's the possibility for the dropping of + * a request here. Que sera sera. + */ + if (self->dieflag) + break; + if (req == NULL) + continue; + if (req->req_handler(req, self) == -1) + log_info("Couldn't handle request"); + req_delete(req); + } + + log_info("Got a kill flag; dying off."); + mutex_lock(&self->fqm->t_cond->lock); + self->status = NOALLOC; + cond_signal(self->fqm->t_cond); + mutex_unlock(&self->fqm->t_cond->lock); + return NULL; +} + +static reqthread_t * +fqm_thr_new(fqm_t *fqm) +{ + reqthread_t *tmp; + + tmp = malloc(sizeof(reqthread_t)); + if (tmp == NULL) { + log_err("Couldn't allocate fallthrough thread: %s.", + strerror(errno)); + return NULL; + } + + tmp->arg = NULL; + tmp->fqm = fqm; + tmp->dieflag = 0; + tmp->status = NOALLOC; + + tmp->tid = malloc(sizeof(thread_t)); + if (tmp->tid == NULL) { + log_err("Couldn't allocate fallthrough thread: %s.", + strerror(errno)); + free(tmp); + return NULL; + } + + if (thread_new(tmp->tid, fqm_popper, tmp)) { + log_err("Couldn't start fallthrough thread: %s.", + strerror(errno)); + free(tmp->tid); + tmp->tid = NULL; + free(tmp); + return NULL; + } + tmp->status = IDLE; + + return tmp; +} + +static int +fqm_thr_wait(fqm_t *fqm) +{ + int deadthreads; + int i; + + deadthreads = 0; + + for (i = 0; i < fqm->maxitems; i++) { + if (fqm->tids[i] && fqm->tids[i]->status == NOALLOC) { + mysqldb_connect_close(fqm->tids[i]->arg); + if (fqm->tids[i]->tid != NULL) + free(fqm->tids[i]->tid); + free(fqm->tids[i]); + fqm->tids[i] = NULL; + deadthreads++; + } + } + + return deadthreads; +} + +fqm_t * +fqm_new(int maxitems) +{ + fqm_t *tmp; + int i; + + tmp = malloc(sizeof(fqm_t)); + if (tmp == NULL) { + log_err("Couldn't create fallthrough queue manager: %s.", + strerror(errno)); + return NULL; + } + + tmp->q_cond = NULL; + tmp->t_cond = NULL; + tmp->tids = NULL; + tmp->sreq = NULL; tmp->ereq = NULL; + tmp->maxitems = 0; + tmp->nitems = 0; + + tmp->q_cond = malloc(sizeof(cond_t)); + if (tmp->q_cond == NULL) { + log_err("Couldn't allocate queue condition variable: %s.", + strerror(errno)); + fqm_delete(tmp); + return NULL; + } + + if (cond_new(tmp->q_cond)) { + log_err("Couldn't initialise queue condition variable: %s.", + strerror(errno)); + fqm_delete(tmp); + return NULL; + } + + tmp->t_cond = malloc(sizeof(cond_t)); + if (tmp->t_cond == NULL) { + log_err("Couldn't allocate queue destroy condition: %s.", + strerror(errno)); + fqm_delete(tmp); + return NULL; + } + + if (cond_new(tmp->t_cond)) { + log_err("Couldn't initialise queue destroy condition: %s.", + strerror(errno)); + fqm_delete(tmp); + return NULL; + } + + tmp->tids = malloc(maxitems * sizeof(reqthread_t *)); + if (tmp->tids == NULL) { + log_err("Couldn't allocate fallthrough queue threads: %s.", + strerror(errno)); + fqm_delete(tmp); + return NULL; + } + + /* Init these so fqm_delete won't break. */ + for (i = 0; i < maxitems; i++) + tmp->tids[i] = NULL; + + /* We cannot adjust max items while threads are busy, so lock. */ + mutex_lock(&tmp->q_cond->lock); + for (i = 0; i < maxitems; i++) { + tmp->tids[i] = fqm_thr_new(tmp); + if (tmp->tids[i] == NULL) { + mutex_unlock(&tmp->q_cond->lock); + fqm_delete(tmp); + return NULL; + } + tmp->maxitems++; + } + mutex_unlock(&tmp->q_cond->lock); + + /* XXX: this may need a lock. */ + fqm = tmp; + return tmp; +} + +/* + * Make sure all threads in this fqm are idle. This is an expensive + * operation, but that's okay, since this code should only be run when + * a client has closed the connection, so we can take as long as we want. + * + * The queue is locked when coming in to this routine and leaving it. + */ +void +verify_idle_threads(fqm_t *fqm) +{ + int i, busy_thread; + + do { + busy_thread = 0; + for (i = 0; i < fqm->maxitems; i++) { + if (fqm->tids[i]->status == BUSY) + busy_thread = 1; + } + + /* + * This is the shitty part. + * We unlock the queue and sleep for a bit to give other + * threads a chance to finish what they're doing. + */ + if (busy_thread) { + mutex_unlock(&fqm->q_cond->lock); + sleep(1); + mutex_lock(&fqm->q_cond->lock); + } + } while (busy_thread); +} + +void +fqm_delete(fqm_t *fqm) +{ + int i; + + if (fqm->tids) { + /* Tell all threads to quit. */ + for (i = 0; i < fqm->maxitems; i++) { + if (fqm->tids[i] != NULL) + fqm->tids[i]->dieflag = 1; + } + + /* + * Lock queue waiting condition to ensure that no + * threads miss this signal. The threads MUST be idle + * in order to guarantee this signal is recieved. + */ + mutex_lock(&fqm->q_cond->lock); + verify_idle_threads(fqm); + pthread_cond_broadcast(&fqm->q_cond->id); + mutex_unlock(&fqm->q_cond->lock); + + /* Now wait for them to die off. */ + i = 0; + while (i < fqm->maxitems) { + mutex_lock(&fqm->t_cond->lock); + i += fqm_thr_wait(fqm); + if (i < fqm->maxitems) + cond_wait(fqm->t_cond); + mutex_unlock(&fqm->t_cond->lock); + } + free(fqm->tids); + fqm->tids = NULL; + } + + /* + * At this point all fqm threads should be dead. + */ + if (fqm->t_cond) { + (void)cond_destroy(fqm->t_cond); + free(fqm->t_cond); + fqm->t_cond = NULL; + } + + if (fqm->q_cond) { + (void)cond_destroy(fqm->q_cond); + free(fqm->q_cond); + fqm->q_cond = NULL; + } + + free(fqm); +} + +int +fqm_changemaxitems(fqm_t *fqm, int maxitems) +{ + reqthread_t **new_tidpool; + int i, j; + + /* + * This code broken. Silently fail here. + */ + return 0; + + if (fqm->maxitems == maxitems) + return 0; + + mutex_lock(&fqm->q_cond->lock); + /* + * Make sure all threads are busy. We can't go changing + * data under them. + */ + verify_idle_threads(fqm); + new_tidpool = malloc(maxitems * sizeof(reqthread_t *)); + if (new_tidpool == NULL) { + mutex_unlock(&fqm->q_cond->lock); + log_err("Couldn't allocate new FQM thread pool: %s.", + strerror(errno)); + return -1; + } + + /* Compress old TID pool. */ + for (j = 0, i = 0; i < fqm->maxitems && j < maxitems; i++) { + if (fqm->tids[i]->status != NOALLOC) { + new_tidpool[j] = fqm->tids[i]; + j++; + } + } + + if (fqm->maxitems < maxitems) { + /* Add more threads. */ + mutex_lock(&fqm->q_cond->lock); + for (i = fqm->maxitems; i < maxitems; i++) { + new_tidpool[i] = fqm_thr_new(fqm); + if (new_tidpool[i] == NULL) { + free(new_tidpool); + mutex_unlock(&fqm->q_cond->lock); + return -1; + } + } + mutex_unlock(&fqm->q_cond->lock); + } else if (fqm->maxitems > maxitems) { + /* Kill some threads. */ + int deadthreads; + + /* Tell them to die, then wake 'em up. */ + for (i = maxitems; i < fqm->maxitems; i++) + fqm->tids[i]->dieflag = 1; + pthread_cond_broadcast(&fqm->q_cond->id); + + deadthreads = 0; + while (deadthreads < fqm->maxitems - maxitems) { + mutex_lock(&fqm->t_cond->lock); + deadthreads += fqm_thr_wait(fqm); + if (deadthreads < fqm->maxitems - maxitems) + cond_wait(fqm->t_cond); + mutex_unlock(&fqm->t_cond->lock); + } + } + + free(fqm->tids); + fqm->tids = new_tidpool; + fqm->maxitems = maxitems; + mutex_unlock(&fqm->q_cond->lock); + return 0; +} + +int +fqm_push(fqm_t *fqm, request_t *req) +{ + if (fqm->nitems == fqm->maxitems) { + log_err("Too many items on the request queue."); + return -1; + } + + /* Lock the queue and add the item. */ + mutex_lock(&fqm->q_cond->lock); + + req->next = NULL; + if (fqm->sreq == NULL) + fqm->sreq = req; + else + fqm->ereq->next = req; + fqm->ereq = req; + fqm->nitems++; + + /* Unlock the queue and signal that there's an item on it. */ + cond_signal(fqm->q_cond); + mutex_unlock(&fqm->q_cond->lock); + return 0; +} diff --git a/server/.svn/text-base/fqm.h.svn-base b/server/.svn/text-base/fqm.h.svn-base new file mode 100644 index 0000000..c3c27df --- /dev/null +++ b/server/.svn/text-base/fqm.h.svn-base @@ -0,0 +1,50 @@ +/* $Id: fqm.h,v 1.9 2000/11/08 19:50:24 shmit Exp $ */ + +#ifndef FQM_H +#define FQM_H + +#include "thread.h" + +#define REQHANDLER(func) int func(struct _request_t *req, reqthread_t *self) + +enum _status_t { IDLE, BUSY, NOALLOC }; +typedef enum _status_t status_t; + +struct _reqthread_t { + struct _fqm_t *fqm; + thread_t *tid; + void *arg; + int dieflag; + status_t status; +}; +typedef struct _reqthread_t reqthread_t; + +struct _request_t { + REQHANDLER((*req_handler)); + char *req; + int sock; + short reqid; + struct _request_t *next; +}; +typedef struct _request_t request_t; + +struct _fqm_t { + cond_t *q_cond; + cond_t *t_cond; + request_t *sreq, *ereq; + reqthread_t **tids; + int maxitems; + int nitems; +}; +typedef struct _fqm_t fqm_t; + +request_t *req_new(int sock, short reqid, REQHANDLER((*req_handler)), + const char *reqstr, int reqlen); +void req_delete(request_t *req); + +fqm_t *fqm_new(int maxitems); +void fqm_delete(fqm_t *fqm); +int fqm_changemaxitems(fqm_t *fqm, int maxitems); +int fqm_push(fqm_t *fqm, request_t *req); + +#endif diff --git a/server/.svn/text-base/log.c.svn-base b/server/.svn/text-base/log.c.svn-base new file mode 100644 index 0000000..612156d --- /dev/null +++ b/server/.svn/text-base/log.c.svn-base @@ -0,0 +1,99 @@ +#include "conf.h" +#include "log.h" + +#include <pthread.h> +#include <stdarg.h> +#include <stdio.h> +#include <sys/time.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> + +RCSID("$Id: log.c,v 1.8 2000/11/13 18:47:17 shmit Exp $"); + +extern char *progname; + +#if 0 +FILE *logf = NULL; +#endif + +static void log_priority(int priority, const char *fmt, va_list args); + +/* + * Log a message with a given priority. + */ +void +log_priority(int priority, const char *fmt, va_list args) +{ + char lbuff[1024]; +#if 0 + char tbuff[256]; + struct tm timeptr; + time_t tloc; +#endif + + (void)snprintf(lbuff, sizeof(lbuff), + "[tid: %d] %s", (int)pthread_self(), fmt); + vsyslog(priority, lbuff, args); + +#if 0 + tloc = time(0); + (void)localtime_r(&tloc, &timeptr); + (void)strftime(tbuff, sizeof(tbuff), "%Y-%h-%d %H:%M:%S", &timeptr); + (void)snprintf(lbuff, sizeof(lbuff), "%s %s[%d:%d] %s\n", + tbuff, progname, getpid(), (int)pthread_self(), fmt); + (void)vfprintf(logf, lbuff, args); +#endif +} + +/* + * Log an error message. + */ +void +log_err(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + log_priority(LOG_ERR, fmt, ap); + va_end(ap); +} + +/* + * Log a warning message. + */ +void +log_warn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + log_priority(LOG_WARNING, fmt, ap); + va_end(ap); +} + +/* + * Log an informational message. + */ +void +log_info(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + log_priority(LOG_INFO, fmt, ap); + va_end(ap); +} + +/* + * Initialize logging facilites. + */ +void +log_open() +{ + openlog(progname, LOG_PID|LOG_PERROR, LOG_DAEMON); + +#if 0 + logf = fopen("/home/shmit/var/log/nastd.log", "a+"); +#endif +} diff --git a/server/.svn/text-base/log.h.svn-base b/server/.svn/text-base/log.h.svn-base new file mode 100644 index 0000000..9aff53a --- /dev/null +++ b/server/.svn/text-base/log.h.svn-base @@ -0,0 +1,11 @@ +/* $Id: log.h,v 1.1 2000/02/29 00:32:12 shmit Exp $ */ + +#ifndef LOG_H +# define LOG_H + +void log_open(); +void log_err(const char *fmt, ...); +void log_warn(const char *fmt, ...); +void log_info(const char *fmt, ...); + +#endif /* LOG_H */ diff --git a/server/.svn/text-base/md5.c.svn-base b/server/.svn/text-base/md5.c.svn-base new file mode 100644 index 0000000..b24f966 --- /dev/null +++ b/server/.svn/text-base/md5.c.svn-base @@ -0,0 +1,308 @@ +/* + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. + * All rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD5 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD5 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +#include "conf.h" +#include "log.h" +#include "md5.h" + +#include <string.h> + +RCSID("$Id: md5.c,v 1.2 2000/03/27 22:23:25 shmit Exp $"); + +/* Constants for MD5Transform routine. */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform(uint32_t *, const unsigned char *); +static void Encode(unsigned char *, uint32_t *, unsigned int, int ouputlen); +static void Decode(uint32_t *, const unsigned char *, unsigned int); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* + * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + * Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +void +md5_calc(unsigned char *output, const unsigned char *input, unsigned int inlen, + int outputlen) +{ + MD5_CTX context; + + MD5Init(&context); + MD5Update(&context, input, inlen); + MD5Final(output, &context, outputlen); +} + +/* + * MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void +MD5Init(MD5_CTX *context) +{ + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* + * MD5 block update operation. Continues an MD5 message-digest + * operation, processing another message block, and updating the + * context. + */ +void +MD5Update(MD5_CTX *context, const unsigned char *input, unsigned int inputLen) +{ + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((uint32_t)inputLen << 3)) < + ((uint32_t)inputLen << 3)) + context->count[1]++; + context->count[1] += ((uint32_t)inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. */ + if (inputLen >= partLen) { + memcpy(&context->buffer[index], input, partLen); + MD5Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } else + i = 0; + + /* Buffer remaining input */ + memcpy(&context->buffer[index], &input[i], inputLen-i); +} + +/* + * MD5 finalization. Ends an MD5 message-digest operation, writing the + * the message digest and zeroizing the context. + */ +void +MD5Final(unsigned char *digest, MD5_CTX *context, int digestlen) +{ + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + Encode(bits, context->count, 8, sizeof(bits)); + + /* Pad out to 56 mod 64. */ + index = (context->count[0] >> 3) & 0x3f; + padLen = (index < 56) ? (56 - index) : (120 - index); + MD5Update(context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update(context, bits, 8); + + /* Store state in digest */ + Encode(digest, context->state, 16, digestlen); + + /* Zeroize sensitive information. */ + memset(context, 0, sizeof(MD5_CTX)); +} + +/* + * MD5 basic transformation. Transforms state based on block. + */ +static void +MD5Transform(uint32_t *state, const unsigned char *block) +{ + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + memset(x, 0, sizeof(x)); +} + +/* + * Encodes input (uint32_t) into output (unsigned char). Assumes len is + * a multiple of 4. + */ +static void +Encode(unsigned char *output, uint32_t *input, unsigned int len, int outputlen) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len && j <= outputlen-4; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } + + if (j > outputlen-4 && j < len) + log_warn("Digest would be too big, truncated."); +} + +/* + * Decodes input (unsigned char) into output (uint32_t). Assumes len is + * a multiple of 4. + */ +static void +Decode(uint32_t *output, const unsigned char *input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) | + (((uint32_t)input[j+2]) << 16) | + (((uint32_t)input[j+3]) << 24); +} diff --git a/server/.svn/text-base/md5.h.svn-base b/server/.svn/text-base/md5.h.svn-base new file mode 100644 index 0000000..5f48d41 --- /dev/null +++ b/server/.svn/text-base/md5.h.svn-base @@ -0,0 +1,48 @@ +/* $Id: md5.h,v 1.2 2000/03/27 22:23:25 shmit Exp $ */ + +/* + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. + * All rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD5 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD5 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +#ifndef MD5_H +# define MD5_H + +#include "compat.h" + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; + +/* MD5 context. */ +typedef struct { + uint32_t state[4]; /* state (ABCD) */ + uint32_t count[2]; /* number of bits, modulo 2^64 */ + /* (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void MD5Init(MD5_CTX *); +void MD5Update(MD5_CTX *, const unsigned char *, unsigned int); +void MD5Final(unsigned char *, MD5_CTX *, int outputlen); +void md5_calc(unsigned char *output, const unsigned char *input, + unsigned int inlen, int outputlen); + +#endif /* MD5_H */ diff --git a/server/.svn/text-base/memdb.c.svn-base b/server/.svn/text-base/memdb.c.svn-base new file mode 100644 index 0000000..501d0ef --- /dev/null +++ b/server/.svn/text-base/memdb.c.svn-base @@ -0,0 +1,501 @@ +#include "conf.h" +#include "config.h" +#include "array.h" +#include "log.h" +#include "md5.h" +#include "memdb.h" +#include "thread.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +RCSID("$Id: memdb.c,v 1.27 2001/10/04 23:57:10 shmit Exp $"); + +#define HASHSIZE 1024 + +extern time_t cdb_mtime; + +enum _cachetype_t { C_DEL, C_UPD, C_TRYVAL, C_EXPIRE }; +typedef enum _cachetype_t cachetype_t; + +struct _mement_t { + char *key; + int keylen; + array_t *vals; + time_t *upd_time; + cachetype_t type; + void *typeval; +}; +typedef struct _mement_t mement_t; + +struct _cachent_t { + mement_t ent; + struct _cachent_t *next; +}; +typedef struct _cachent_t cachent_t; + +struct _counter_t { + float onemin, fivemin, fifteenmin; +}; +typedef struct _counter_t counter_t; + +extern short db_fieldcount; + +static cachent_t **memdb = NULL; +static int memdbsize; +static rw_mutex_t *memdb_lk = NULL; + +static int query_sec, add_sec, del_sec, upd_sec; +static counter_t queryrate; +static counter_t addrate; +static counter_t delrate; +static counter_t updrate; + +static unsigned int +hashkey(const char *key, int keylen) +{ + char md5hash[32]; + unsigned int rc; + + memset(md5hash, 0, sizeof(md5hash)); + md5_calc(md5hash, key, keylen, sizeof(md5hash)); + memcpy(&rc, md5hash, sizeof(rc)); + return (rc % HASHSIZE); +} + +static void +ent_delete(mement_t *ent) +{ + if (ent == NULL) + return; + + if (ent->key != NULL) + free(ent->key); + if (ent->vals != NULL) + array_delete(ent->vals); + if (ent->upd_time != NULL) + free(ent->upd_time); + if (ent->typeval != NULL) + free(ent->typeval); +} + +int +memdb_new() +{ + cachent_t **newdb; + int i; + int rc; + + log_info("Initialising memdb interface."); + + if (memdb_lk == NULL) { + memdb_lk = malloc(sizeof(rw_mutex_t)); + if (memdb_lk == NULL) { + log_err("Couldn't allocate memdb mutex: %s.", + strerror(errno)); + return -1; + } + rc = rw_mutex_new(memdb_lk); + if (rc) { + log_err("Couldn't initialise memdb mutex: %s.", + strerror(rc)); + return -1; + } + } + + newdb = malloc(HASHSIZE * sizeof(cachent_t *)); + if (newdb == NULL) { + log_err("Couldn't allocate new memdb: %s.", strerror(errno)); + return -1; + } + + for (i = 0; i < HASHSIZE; i++) + newdb[i] = NULL; + + rw_mutex_write_lock(memdb_lk); + if (memdb != NULL) + memdb_delete(memdb); + memdb = newdb; + rw_mutex_unlock(memdb_lk); + + query_sec = add_sec = del_sec = upd_sec = 0; + queryrate.onemin = queryrate.fivemin = queryrate.fifteenmin = 0; + addrate.onemin = addrate.fivemin = addrate.fifteenmin = 0; + delrate.onemin = delrate.fivemin = delrate.fifteenmin = 0; + updrate.onemin = updrate.fivemin = updrate.fifteenmin = 0; + memdbsize = 0; + + log_info("memdb interface initialised."); + return 0; +} + +void +memdb_delete() +{ + int i; + + if (memdb == NULL) + return; + + for (i = 0; i < HASHSIZE; i++) { + cachent_t *p; + + p = memdb[i]; + while (p != NULL) { + cachent_t *q; + + q = p->next; + ent_delete(&p->ent); + free(p); + p = q; + } + } + free(memdb); + memdb = NULL; +} + +int +memdb_add(const char *key, int keylen, array_t *vals) +{ + cachent_t *ent; + int hkey; + time_t curtime; + + ent = malloc(sizeof(cachent_t)); + if (ent == NULL) { + log_err("Couldn't create memdb entry for `%s': %s.", + key, strerror(errno)); + return -1; + } + ent->next = NULL; + ent->ent.key = NULL; + ent->ent.type = C_UPD; + ent->ent.typeval = NULL; + ent->ent.upd_time = NULL; + + ent->ent.key = malloc((keylen + 1) * sizeof(char)); + if (ent->ent.key == NULL) { + log_err("Couldn't create entry key for `%s': %s.", + key, strerror(errno)); + ent_delete(&ent->ent); + return -1; + } + memcpy(ent->ent.key, key, keylen); + ent->ent.keylen = keylen; + + ent->ent.vals = array_new(); + if (ent->ent.vals == NULL) { + ent_delete(&ent->ent); + return -1; + } + if (array_dup(ent->ent.vals, vals) == -1) { + ent_delete(&ent->ent); + return -1; + } + + ent->ent.upd_time = malloc(sizeof(time_t)); + if (ent->ent.upd_time == NULL) { + ent_delete(&ent->ent); + return -1; + } + curtime = time(NULL); + memcpy(ent->ent.upd_time, &curtime, sizeof(time_t)); + + /* Cache non-results for a minute. */ + if (vals->nitems == 0) { + time_t expire; + + ent->ent.type = C_EXPIRE; + ent->ent.typeval = malloc(sizeof(time_t)); + expire = time(NULL); + expire += config.null_cache_timeout; + memcpy(ent->ent.typeval, &expire, sizeof(time_t)); + } + + hkey = hashkey(key, keylen); + rw_mutex_write_lock(memdb_lk); + if (memdb[hkey] == NULL) { + memdb[hkey] = ent; + memdbsize++; + } else { + cachent_t *p, *q; + + p = memdb[hkey]; + q = NULL; + while (p->next != NULL && + !(keylen == p->ent.keylen && + memcmp(p->ent.key, key, p->ent.keylen) == 0)) { + q = p; + p = p->next; + } + if (keylen == p->ent.keylen && + memcmp(p->ent.key, key, keylen) == 0) { + /* Already in memdb. */ + + log_info("(add) %s already exists.", key); + + switch (p->ent.type) { + case C_EXPIRE: + case C_DEL: + /* + * Deletable entries. Trash 'em and + * add 'em. + */ + + if (q == NULL) + memdb[hkey] = ent; + else + q->next = ent; + ent->next = p->next; + + ent_delete(&p->ent); + free(p); + break; + default: + /* XXX: Do an update instead of an add. */ + } + } else { + p->next = ent; + memdbsize++; + } + } + + add_sec++; + rw_mutex_unlock(memdb_lk); + return 0; +} + +int +memdb_del(const char *key, int keylen) +{ + cachent_t *p; + int hkey; + + hkey = hashkey(key, keylen); + + rw_mutex_read_lock(memdb_lk); + p = memdb[hkey]; + while (p != NULL && + (keylen != p->ent.keylen || memcmp(p->ent.key, key, keylen))) + p = p->next; + + if (p == NULL) { + array_t *aa; + + /* + * Entry not found. We have to add it ourselves. + */ + rw_mutex_unlock(memdb_lk); + + aa = array_new(); + if (aa == NULL) + return -1; + if (memdb_add(key, keylen, aa) == -1) + return -1; + + /* + * The entry has been added - now go back and mark it + * for deletion. + */ + return memdb_del(key, keylen); + } + + rw_mutex_write_lock(memdb_lk); + if (p->ent.typeval != NULL) { + free(p->ent.typeval); + p->ent.typeval = NULL; + } + + p->ent.type = C_DEL; + if (p->ent.vals != NULL) + array_delete(p->ent.vals); + + del_sec++; + rw_mutex_unlock(memdb_lk); + + return 0; +} + +int +memdb_get(const char *key, int keylen, array_t *vals) +{ + cachent_t *p, *q; + int hkey; + + hkey = hashkey(key, keylen); + rw_mutex_read_lock(memdb_lk); + p = memdb[hkey]; + q = NULL; + while (p != NULL && + (keylen != p->ent.keylen || memcmp(p->ent.key, key, keylen))) { + q = p; + p = p->next; + } + + if (p == NULL) { + rw_mutex_unlock(memdb_lk); + return -1; + } + + switch (p->ent.type) { + case C_DEL: + rw_mutex_unlock(memdb_lk); + query_sec++; + return 0; + case C_EXPIRE: + if (p->ent.typeval != NULL) { + time_t now, expire; + + now = time(NULL); + expire = *((time_t *)p->ent.typeval); + if (now >= expire) { + ent_delete(&p->ent); + if (q != NULL) + q->next = p->next; + else + memdb[hkey] = p->next; + free(p); + rw_mutex_unlock(memdb_lk); + log_info("DEBUG: (get) %s has expired", key); + return -1; + } + } + break; + default: + if (p->ent.upd_time != NULL) { + time_t upd_time; + + upd_time = *p->ent.upd_time; + if (cdb_mtime > upd_time) { + ent_delete(&p->ent); + if (q != NULL) + q->next = p->next; + else + memdb[hkey] = p->next; + free(p); + rw_mutex_unlock(memdb_lk); + log_info("DEBUG: (get) %s is out of date", key); + return -1; + } + } + break; + } + + if (array_dup(vals, p->ent.vals) == -1) { + rw_mutex_unlock(memdb_lk); + return -1; + } + + rw_mutex_unlock(memdb_lk); + query_sec++; + return 0; +} + +int +memdb_upd(const char *key, int keylen, array_t *vals) +{ + cachent_t *p; + int hkey; + time_t curtime; + + /* First make sure that we have enough values. */ + if (vals->nitems != db_fieldcount) { + log_err("Update tried with wrong value count."); + return -1; + } + + hkey = hashkey(key, keylen); + rw_mutex_read_lock(memdb_lk); + p = memdb[hkey]; + while (p != NULL && + (keylen != p->ent.keylen || memcmp(p->ent.key, key, keylen))) + p = p->next; + + if (p == NULL) { + /* Entry not found. Add it ourselves. */ + rw_mutex_unlock(memdb_lk); + return memdb_add(key, keylen, vals); + } + rw_mutex_unlock(memdb_lk); + + /* Entry found, lets replace it with our copy. */ + + rw_mutex_write_lock(memdb_lk); + p->ent.type = C_UPD; + p->ent.typeval = NULL; + curtime = time(NULL); + memcpy(p->ent.upd_time, &curtime, sizeof(time_t)); + array_delete(p->ent.vals); + + p->ent.vals = array_new(); + if (p->ent.vals == NULL) { + rw_mutex_unlock(memdb_lk); + return -1; + } + + if (array_dup(p->ent.vals, vals) == -1) { + rw_mutex_unlock(memdb_lk); + return -1; + } + + upd_sec++; + rw_mutex_unlock(memdb_lk); + + return 0; +} + +int +memdb_stats(array_t *statarr) +{ + char buffer[512]; + + /* Convert q/m, q/5m, and q/15m into q/s. */ + snprintf(buffer, sizeof(buffer), "MEMDB get: %.2f, %.2f, %.2f", + queryrate.onemin, queryrate.fivemin, queryrate.fifteenmin); + if (array_add(statarr, strlen(buffer), buffer, ARRTERM) == -1) + return -1; + + snprintf(buffer, sizeof(buffer), "MEMDB add: %.2f, %.2f, %.2f", + addrate.onemin, addrate.fivemin, addrate.fifteenmin); + if (array_add(statarr, strlen(buffer), buffer, ARRTERM) == -1) + return -1; + + snprintf(buffer, sizeof(buffer), "MEMDB del: %.2f, %.2f, %.2f", + delrate.onemin, delrate.fivemin, delrate.fifteenmin); + if (array_add(statarr, strlen(buffer), buffer, ARRTERM) == -1) + return -1; + + snprintf(buffer, sizeof(buffer), "MEMDB upd: %.2f, %.2f, %.2f", + updrate.onemin, updrate.fivemin, updrate.fifteenmin); + if (array_add(statarr, strlen(buffer), buffer, ARRTERM) == -1) + return -1; + + snprintf(buffer, sizeof(buffer), "MEMDB total entries: %d", memdbsize); + return array_add(statarr, strlen(buffer), buffer, ARRTERM); +} + +void +memdb_collate() +{ + queryrate.onemin = ((queryrate.onemin * 59) + query_sec) / 60; + queryrate.fivemin = ((queryrate.fivemin * 299) + query_sec) / 300; + queryrate.fifteenmin = ((queryrate.fifteenmin * 899) + query_sec) / 900; + query_sec = 0; + + addrate.onemin = ((addrate.onemin * 59) + add_sec) / 60; + addrate.fivemin = ((addrate.fivemin * 299) + add_sec) / 300; + addrate.fifteenmin = ((addrate.fifteenmin * 899) + add_sec) / 900; + add_sec = 0; + + delrate.onemin = ((delrate.onemin * 59) + del_sec) / 60; + delrate.fivemin = ((delrate.fivemin * 299) + del_sec) / 300; + delrate.fifteenmin = ((delrate.fifteenmin * 899) + del_sec) / 900; + del_sec = 0; + + updrate.onemin = ((updrate.onemin * 59) + upd_sec) / 60; + updrate.fivemin = ((updrate.fivemin * 299) + upd_sec) / 300; + updrate.fifteenmin = ((updrate.fifteenmin * 899) + upd_sec) / 900; + upd_sec = 0; +} diff --git a/server/.svn/text-base/memdb.h.svn-base b/server/.svn/text-base/memdb.h.svn-base new file mode 100644 index 0000000..0822e61 --- /dev/null +++ b/server/.svn/text-base/memdb.h.svn-base @@ -0,0 +1,17 @@ +/* $Id: memdb.h,v 1.8 2000/05/17 19:32:58 shmit Exp $ */ + +#ifndef MEMDB_H +#define MEMDB_H + +int memdb_new(); +void memdb_delete(); + +int memdb_add(const char *key, int keylen, array_t *vals); +int memdb_del(const char *key, int keylen); +int memdb_get(const char *key, int keylen, array_t *vals); +int memdb_upd(const char *key, int keylen, array_t *vals); + +int memdb_stats(array_t *statarr); +void memdb_collate(); + +#endif diff --git a/server/.svn/text-base/mysqldb.c.svn-base b/server/.svn/text-base/mysqldb.c.svn-base new file mode 100644 index 0000000..517c15b --- /dev/null +++ b/server/.svn/text-base/mysqldb.c.svn-base @@ -0,0 +1,163 @@ +#include "conf.h" +#include "array.h" +#include "config.h" +#include "nastdio.h" +#include "log.h" +#include "mysqldb.h" +#include "thread.h" + +#include <errno.h> +#include <errmsg.h> +#include <mysql.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +RCSID("$Id: mysqldb.c,v 1.30 2001/10/10 20:29:47 shmit Exp $"); + +extern fieldent *db_fields; +extern char db_key[1024]; +extern char db_dbn[1024]; +extern char db_tbl[1024]; +extern short db_fieldcount; + +static char cols[512]; + +static int sec_c; +static float onemin_c, fivemin_c, fifteenmin_c; + +int +mysqldb_new() +{ + int i; + + sec_c = 0; + onemin_c = fivemin_c = fifteenmin_c = 0; + + cols[0] = '\0'; + for (i = 0; i < db_fieldcount; i++) { + strncat(cols, db_fields[i].name, sizeof(cols)); + if (i < db_fieldcount-1) + strncat(cols, ",", sizeof(cols)); + } + + return 0; +} + +void * +mysqldb_connect_new() +{ + MYSQL *dbh; + + log_info("Initialising MySQL database."); + + dbh = mysql_init(NULL); + if (dbh == NULL) { + log_err("Couldn't allocate mysql handle: %s.", + strerror(errno)); + return NULL; + } + + if (!mysql_connect(dbh, config.mysql_host, + config.mysql_user, config.mysql_pass)) { + log_err("Couldn't open connection to database: %s.", + mysql_error(dbh)); + mysqldb_connect_close(dbh); + return NULL; + } + + if (mysql_select_db(dbh, db_dbn)) { + log_err("Couldn't open database: %s.", + mysql_error(dbh)); + mysqldb_connect_close(dbh); + return NULL; + } + + log_info("MySQL database interface initialised."); + return (void *)dbh; +} + +void +mysqldb_connect_close(void *dbh) +{ + if (dbh != NULL) { + log_info("MySQL connection shutting down."); + mysql_close(dbh); + free(dbh); + } +} + +int +mysqldb_get(reqthread_t *self, const char *key, int keylen, array_t *aa) +{ + MYSQL *dbh; + MYSQL_RES *result; + char buffer[1024]; + MYSQL_ROW row; + int i, rc; + + snprintf(buffer, sizeof(buffer), DBSELECT, cols, db_tbl, db_key, key); + + if (self->arg == NULL) { + self->arg = mysqldb_connect_new(); + if (self->arg == NULL) + return -1; + } + dbh = (MYSQL *)self->arg; + + rc = mysql_query(dbh, buffer); + if (rc) { + log_err("Error performing query: %s.", mysql_error(dbh)); + mysqldb_connect_close(dbh); + self->arg = NULL; + return -1; + } + + result = mysql_use_result(dbh); + row = mysql_fetch_row(result); + if (row == NULL) { + log_info("Couldn't find %s in MySQL database.", + key); + mysql_free_result(result); + sec_c++; + return 1; + } + + if (mysql_num_fields(result) < db_fieldcount) { + log_err("MySQL server didn't return all fields."); + mysql_free_result(result); + return 0; + } + + for (i = 0; i < db_fieldcount; i++) { + if (array_add(aa, strlen(row[i]), row[i], ARRTERM) == -1) { + mysql_free_result(result); + return -1; + } + } + while (mysql_fetch_row(result)); + mysql_free_result(result); + + sec_c++; + + return 0; +} + +int +mysqldb_stats(array_t *statarr) +{ + char buffer[512]; + + snprintf(buffer, sizeof(buffer), "MySQL: %.2f, %.2f, %.2f", + onemin_c, fivemin_c, fifteenmin_c); + return array_add(statarr, strlen(buffer), buffer, ARRTERM); +} + +void +mysqldb_collate() +{ + onemin_c = ((onemin_c * 59) + sec_c) / 60; + fivemin_c = ((fivemin_c * 299) + sec_c) / 300; + fifteenmin_c = ((fifteenmin_c * 899) + sec_c) / 900; + sec_c = 0; +} diff --git a/server/.svn/text-base/mysqldb.h.svn-base b/server/.svn/text-base/mysqldb.h.svn-base new file mode 100644 index 0000000..c5c703c --- /dev/null +++ b/server/.svn/text-base/mysqldb.h.svn-base @@ -0,0 +1,17 @@ +/* $Id: mysqldb.h,v 1.7 2000/11/08 20:04:55 shmit Exp $ */ + +#ifndef MYSQLDB_H +#define MYSQLDB_H + +#include "array.h" +#include "fqm.h" + +int mysqldb_new(); +void *mysqldb_connect_new(); +void mysqldb_connect_close(void *dbh); +int mysqldb_get(reqthread_t *self, const char *key, int keylen, array_t *aa); + +int mysqldb_stats(array_t *statarr); +void mysqldb_collate(); + +#endif diff --git a/server/.svn/text-base/nastd.c.svn-base b/server/.svn/text-base/nastd.c.svn-base new file mode 100644 index 0000000..3c015a6 --- /dev/null +++ b/server/.svn/text-base/nastd.c.svn-base @@ -0,0 +1,224 @@ +#include "conf.h" +#include "config.h" +#include "nastdio.h" +#include "nastipc.h" +#include "cdb.h" +#include "fqm.h" +#include "log.h" +#include "memdb.h" +#include "mysqldb.h" +#include "periodic.h" + +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <time.h> +#include <unistd.h> + +RCSID("$Id: nastd.c,v 1.8 2001/11/09 15:54:38 shmit Exp $"); + +char *progname; +time_t start_time; + +static int +make_u_csock() +{ + struct sockaddr_un sunix; + int sock; + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock == -1) { + log_err("Couldn't create unix socket: %s.", strerror(errno)); + return -1; + } + + memset(&sunix, 0, sizeof(sunix)); + snprintf(sunix.sun_path, sizeof(sunix.sun_path), config.nast_sock); + sunix.sun_family = AF_UNIX; + (void)unlink(sunix.sun_path); + + if (bind(sock, (struct sockaddr *)&sunix, sizeof(sunix)) == -1) { + log_err("Couldn't bind to unix socket: %s.", strerror(errno)); + return -1; + } + (void)listen(sock, 10); + + return sock; +} + +static int +make_i_csock() +{ + struct sockaddr_in sinet; + int sock; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) { + log_err("Couldn't create inet socket: %S.", strerror(errno)); + return -1; + } + + memset(&sinet, 0, sizeof(sinet)); + sinet.sin_family = AF_INET; + sinet.sin_addr.s_addr = INADDR_ANY; + sinet.sin_port = htons(config.tcp_port); + if (bind(sock, (struct sockaddr *)&sinet, sizeof(sinet)) == -1) { + log_err("Couldn't bind to inet socket: %s.", strerror(errno)); + return -1; + } + (void)listen(sock, 10); + + return sock; +} + +static int +do_client_connect(int sock) +{ + struct sockaddr_un saremote; + int addrlen; + int s; + + addrlen = sizeof(saremote); + s = accept(sock, (struct sockaddr *)&saremote, &addrlen); + if (s == -1) { + log_err("Couldn't accept new connection: %s.", + strerror(errno)); + return -1; + } + io_new(s); + + return 0; +} + +static int +init_daemon() +{ + sigset_t sigmask; + + log_open(); + if (cdb_new()) + return -1; + mysqldb_new(); + if (memdb_new()) + return -1; + + /* + * Turn off SIGPIPE. The calls to write() will return fine with + * it off, and this means we don't have to do any signal mojo. + */ + (void)sigemptyset(&sigmask); + (void)sigaddset(&sigmask, SIGPIPE); + (void)sigprocmask(SIG_BLOCK, &sigmask, NULL); + + /* Now we daemonise. */ + switch (fork()) { + case 0: + setsid(); + close(STDIN_FILENO); + close(STDOUT_FILENO); + break; + case -1: + log_err("Couldn't fork into daemon: %s.", strerror(errno)); + return -1; + default: + exit(0); + } + + return 0; +} + +void +usage() +{ + fprintf(stderr, "Usage: %s [options]\n" + "\t-d directory\tSpecify directory for nast files.\n", + progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char ch; + int u_csock, i_csock; + + progname = strrchr(argv[0], '/'); + if (!progname) + progname = argv[0]; + else + progname++; + + /* Initialise configuration values from file. */ + config_setdefaults(); + while ((ch = getopt(argc, argv, "d:")) != -1) { + switch (ch) { + case 'd': + config.nast_dir = optarg; + break; + default: + usage(); + /* NOTREACHED */ + } + } + if (config_init()) + return 1; + + if (init_daemon()) { + log_err("Couldn't initialise nastd. Exiting."); + return 1; + } + + u_csock = make_u_csock(); + if (u_csock == -1) + return 1; + + i_csock = make_i_csock(); + if (i_csock == -1) + return 1; + + /* Create the FQM threads. */ + (void)fqm_new(10); + + /* + * Creat a thread that runs periodically. + */ + if (periodic_new() == -1) { + log_err("Couldn't start periodic thread. Exiting."); + return 1; + } + + start_time = time(NULL); + + /* + * Main control loop. Sit on the socket and wait for a client to + * connect. As soon as it does, make another thread to handle it. + */ + for (;;) { + fd_set read_fds; + int rc; + + FD_ZERO(&read_fds); + FD_SET(i_csock, &read_fds); + FD_SET(u_csock, &read_fds); + + rc = select(10, &read_fds, NULL, NULL, NULL); + if (rc == -1) { + log_err("Couldn't select on sockets: %s.", + strerror(errno)); + sleep(30); + } + + if (FD_ISSET(i_csock, &read_fds)) + (void)do_client_connect(i_csock); + + if (FD_ISSET(u_csock, &read_fds)) + (void)do_client_connect(u_csock); + } + return 0; +} diff --git a/server/.svn/text-base/nastdio.c.svn-base b/server/.svn/text-base/nastdio.c.svn-base new file mode 100644 index 0000000..dd7ccd3 --- /dev/null +++ b/server/.svn/text-base/nastdio.c.svn-base @@ -0,0 +1,701 @@ +#include "conf.h" +#include "array.h" +#include "nastd.h" +#include "nastdio.h" +#include "nastipc.h" +#include "cdb.h" +#include "fqm.h" +#include "log.h" +#include "memdb.h" +#include "mysqldb.h" +#include "thread.h" + +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> + +RCSID("$Id: nastdio.c,v 1.13 2001/10/29 11:17:13 shmit Exp $"); + +extern fqm_t *fqm; + +extern fieldent *db_fields; +extern char db_key[1024]; +extern short db_fieldcount; + +extern time_t start_time; + +struct _client_opts { + nast_options *opts; + rw_mutex_t *opt_lk; + thread_t *tid; + int sock; +}; +typedef struct _client_opts client_opts; + +static int +arr_send_response(int sock, short reqid, char r_code, array_t *aa) +{ + char *s; + char buffer[1024]; + short l, i; + ssize_t wrote; + + /* Save space for buffer length. */ + l = sizeof(short); + + /* Add request ID. */ + memcpy(buffer+l, &htons(reqid), sizeof(reqid)); + l += sizeof(reqid); + + /* Add OK or ERR. */ + buffer[l] = r_code; + l += sizeof(char); + + /* + * Build the string to be sent back to the client. + */ + for (i = 0; i < aa->nitems; i++) { + int slen; + + s = aa->items[i]->str; + slen = aa->items[i]->strlen; + if (l+slen > sizeof(buffer)) { + log_err("Buffer isn't big enough for all data."); + return -1; + } + memcpy(buffer+l, s, slen); + l += slen; + + if (i < aa->nitems-1) { + buffer[l] = NASTSEP; + l++; + } + } + + /* Fill in buffer length. */ + memcpy(buffer, &htons(l), sizeof(short)); + + wrote = 0; + while (wrote < l) { + ssize_t rc; + + rc = write(sock, buffer + wrote, l - wrote); + if (rc == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + log_err("Couldn't write response: %s.", + strerror(errno)); + return -1; + } + wrote += rc; + } + + return 0; +} + +static int +send_response(int sock, short reqid, char r_code, ...) +{ + array_t *aa; + int rc; + va_list ap; + + aa = array_new(); + va_start(ap, r_code); + if (va_array_add(aa, ap) == -1) { + va_end(ap); + array_delete(aa); + return -1; + } + va_end(ap); + + rc = arr_send_response(sock, reqid, r_code, aa); + array_delete(aa); + return rc; +} + +static int +do_opt_set(int s, short reqid, client_opts *cops, const char *buffer, + size_t bufflen) +{ + int i; + + rw_mutex_write_lock(cops->opt_lk); + for (i = 0; i < bufflen; i += 2) { + switch (buffer[i]) { + case OPTQCACHE: + if (buffer[i+1] == OPTFALSE) + cops->opts->use_qcache = NASTFALSE; + else + cops->opts->use_qcache = NASTTRUE; + break; + case OPTLOCALDB: + if (buffer[i+1] == OPTFALSE) + cops->opts->use_localdb = NASTFALSE; + else + cops->opts->use_localdb = NASTTRUE; + break; + case OPTFALLASYNC: + if (buffer[i+1] == OPTFALSE) + cops->opts->fallthrough_async = NASTFALSE; + else + cops->opts->fallthrough_async = NASTTRUE; + break; + case OPTALWAYSFALL: + if (buffer[i+1] == OPTFALSE) + cops->opts->always_fallthrough = NASTFALSE; + else + cops->opts->always_fallthrough = NASTTRUE; + break; + case OPTFAILONCE: + if (buffer[i+1] == OPTFALSE) + cops->opts->fail_once = NASTFALSE; + else + cops->opts->fail_once = NASTTRUE; + break; + case OPTNOFALLTHROUGH: + if (buffer[i+1] == OPTFALSE) + cops->opts->no_fallthrough = NASTFALSE; + else + cops->opts->no_fallthrough = NASTTRUE; + break; + default: + rw_mutex_unlock(cops->opt_lk); + log_err("Unknown option: `0x%x'.\n", buffer[i]); + (void)send_response(s, reqid, NASTERR, + strlen("Sent unknown option"), + "Sent unknown option", ARRTERM); + return -1; + } + } + rw_mutex_unlock(cops->opt_lk); + + if (send_response(s, reqid, NASTOK, ARRTERM) == -1) + return -1; + return 0; +} + +static int +do_opt_get(int s, short reqid, client_opts *cops) +{ + char buffer[512]; + int bufflen; + + bufflen = 0; + rw_mutex_read_lock(cops->opt_lk); + + buffer[bufflen] = OPTQCACHE; + if (cops->opts->use_qcache) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTLOCALDB; + if (cops->opts->use_localdb) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTFALLASYNC; + if (cops->opts->fallthrough_async) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTALWAYSFALL; + if (cops->opts->always_fallthrough) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTFAILONCE; + if (cops->opts->fail_once) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTNOFALLTHROUGH; + if (cops->opts->no_fallthrough) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = '\0'; + + rw_mutex_unlock(cops->opt_lk); + + if (send_response(s, reqid, NASTOK, bufflen, buffer, ARRTERM) == -1) + return -1; + return 0; +} + +static +REQHANDLER(do_fallthrough) +{ + array_t *aa; + int rc; + + aa = array_new(); + if (aa == NULL) { + log_info("Couldn't allocate array: %s.", strerror(errno)); + (void)send_response(req->sock, req->reqid, NASTERR, + strlen("Couldn't allocate return buffer"), + "Couldn't allocate return buffer", ARRTERM); + return -1; + } + + rc = mysqldb_get(self, req->req, strlen(req->req), aa); + if (rc == -1) { + log_info("Couldn't find %s in MySQL DB.", req->req); + rc = send_response(req->sock, req->reqid, NASTOK, ARRTERM); + array_delete(aa); + return -1; + } + + if (arr_send_response(req->sock, req->reqid, NASTOK, aa) == -1) { + array_delete(aa); + return -1; + } + + /* If we're this far, the memdb doesn't have this key. Add it. */ + (void)memdb_add(req->req, strlen(req->req), aa); + + array_delete(aa); + + return 0; +} + +static int +do_get(int s, short reqid, client_opts *cops, const char *buffer, + size_t bufflen) +{ + int fallthrough_flag; + array_t *aa; + + aa = array_new(); + if (aa == NULL) { + log_info("Couldn't allocate array: %s.", strerror(errno)); + (void)send_response(s, reqid, NASTERR, + strlen("Couldn't allocate return buffer"), + "Couldn't allocate return buffer", ARRTERM); + return -1; + } + + /* Check memdb first. */ + if (cops->opts->use_qcache && !cops->opts->always_fallthrough) { + if (memdb_get(buffer, bufflen, aa) == 0) { + log_info("Found `%s' in memdb.", buffer); + if (arr_send_response(s, reqid, NASTOK, aa) == -1) { + array_delete(aa); + return -1; + } + array_delete(aa); + return 0; + } + } + + /* Just do a CDB lookup for now. */ + if (!cops->opts->always_fallthrough && cops->opts->use_localdb) { + fallthrough_flag = cdb_get(buffer, bufflen, aa); + if (fallthrough_flag == -1) + log_info("Couldn't find `%s' in CDB file.", buffer); + } else { + fallthrough_flag = -1; + } + + /* + * If fallthrough_flag is -1, then the CDB query failed, so + * we should check fallthrough. + */ + if (fallthrough_flag == -1 && !cops->opts->no_fallthrough) { + request_t *req; + + array_delete(aa); + + log_info("Checking fallthrough for `%s'.", buffer); + req = req_new(s, reqid, do_fallthrough, + buffer, bufflen); + if (req == NULL) { + log_err("Couldn't build request for FQM."); + send_response(s, reqid, NASTERR, + strlen("Couldn't build FQM req"), + "Couldn't build FQM req", ARRTERM); + return -1; + } + + if (fqm_push(fqm, req) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't add req to FQM"), + "Couldn't add req to FQM", ARRTERM); + req_delete(req); + return -1; + } + return 0; + } + + if (arr_send_response(s, reqid, NASTOK, aa) == -1) { + array_delete(aa); + return -1; + } + array_delete(aa); + + return 0; +} + +static array_t * +build_array(const char *buff, size_t bufflen) +{ + array_t *aa; + const char *ep, *sp; + + aa = array_new(); + if (aa == NULL) { + log_err("Couldn't allocate array for input buffer."); + return NULL; + } + + sp = buff; + for (ep = sp; ep <= buff+bufflen; ep++) { + if ((ep == buff+bufflen || *ep == NASTSEP) && + ep - sp > 0) { + if (array_add(aa, ep-sp, sp, ARRTERM) == -1) { + log_err("Couldn't add item to input array."); + array_delete(aa); + return NULL; + } + sp = ep+1; + } + } + + return aa; +} + +static int +do_update(int s, short reqid, client_opts *cops, const char *buffer, + size_t bufflen) +{ + array_t *aa; + char *key; + int keylen; + + for (keylen = 0; keylen < bufflen; keylen++) { + if (buffer[keylen] == NASTSEP) + break; + } + + if (keylen == bufflen) { + /* Request only contains key. That's bad. */ + return send_response(s, reqid, NASTERR, + strlen("Need values for update"), + "Need values for update", ARRTERM); + } + + key = malloc(sizeof(char) * keylen + 1); + if (key == NULL) { + log_err("Couldn't allocate key for update: %s.", + strerror(errno)); + send_response(s, reqid, NASTERR, + strlen("Couldn't allocate key"), + "Couldn't allocate key", ARRTERM); + return -1; + } + memcpy(key, buffer, keylen); + key[keylen + 1] = '\0'; + + aa = build_array(buffer+keylen + 1, bufflen-keylen - 1); + if (aa == NULL) { + send_response(s, reqid, NASTERR, + strlen("Couldn't build your input array"), + "Couldn't build your input array", ARRTERM); + return -1; + } + + if (memdb_upd(key, keylen, aa) == -1) { + array_delete(aa); + return send_response(s, reqid, NASTERR, + strlen("Couldn't update cache"), + "Couldn't update cache", ARRTERM); + } + array_delete(aa); + + return send_response(s, reqid, NASTOK, ARRTERM); +} + +static int +do_stats(int s, int reqid) +{ + array_t *aa; + char buffer[512]; + int up_day, up_hour, up_min, up_sec; + time_t uptime; + + aa = array_new(); + + /* Gather stats from the various databases. */ + if (mysqldb_stats(aa) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't get stats from MySQL"), + "Couldn't get stats from MySQL", ARRTERM); + array_delete(aa); + return -1; + } + + if (cdb_stats(aa) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't get stats from cdb"), + "Couldn't get stats from cdb", ARRTERM); + array_delete(aa); + return -1; + } + + if (memdb_stats(aa) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't get stats from memdb"), + "Couldn't get stats from memdb", ARRTERM); + array_delete(aa); + return -1; + } + + uptime = time(NULL) - start_time; + up_day = uptime / 86400; uptime -= up_day * 86400; + up_hour = uptime / 3600; uptime -= up_hour * 3600; + up_min = uptime / 60; uptime -= up_min * 60; + up_sec = uptime; + + snprintf(buffer, sizeof(buffer), + "Uptime: %d day(s), %02d:%02d:%02d", + up_day, up_hour, up_min, up_sec); + if (array_add(aa, strlen(buffer), buffer, ARRTERM) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't return uptime"), + "Couldn't return uptime", ARRTERM); + array_delete(aa); + return -1; + } + + snprintf(buffer, sizeof(buffer), + "Version: %s", VERSION); + if (array_add(aa, strlen(buffer), buffer, ARRTERM) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't return version"), + "Couldn't return version", ARRTERM); + array_delete(aa); + return -1; + } + + /* Now send 'em off. */ + if (arr_send_response(s, reqid, NASTOK, aa) == -1) { + array_delete(aa); + return -1; + } + array_delete(aa); + return 0; +} + +static int +process_cmd(int s, client_opts *cops, const char *buffer, size_t bufflen) +{ + const char *p; + int l; + short len, reqid; + + /* + * bufflen must be at least six bytes or we have a screwed up + * command. + */ + if (bufflen < sizeof(len) + sizeof(reqid) + 2*sizeof(char)) { + log_err("Command sent is too short."); + return -1; + } + + for (p = buffer; p < buffer+bufflen; p += len) { + /* All requests start with a length. */ + memcpy(&len, p, sizeof(reqid)); + len = ntohs(len); + l = sizeof(len); + + /* Follow with a request ID. */ + memcpy(&reqid, p+l, sizeof(reqid)); + reqid = ntohs(reqid); + l += sizeof(reqid); + + /* Then have NASTCMD. Make sure it's there. */ + if (p[l] != NASTCMD) { + log_err("Command doesn't start with NASTCMD."); + return -1; + } + l += sizeof(char); + + /* The next byte says what kind of command it is. */ + switch (p[l++]) { + case NASTDIE: + return 1; + break; + case NASTOPTSET: + if (do_opt_set(s, reqid, cops, p+l, len-l) == -1) + return -1; + break; + case NASTOPTGET: + if (do_opt_get(s, reqid, cops) == -1) + return -1; + break; + case NASTGET: + if (do_get(s, reqid, cops, p+l, len-l) == -1) + return -1; + break; + case NASTADD: + log_err("Add command not supported yet."); + break; + case NASTDEL: + log_err("Delete command not supported yet."); + break; + case NASTUPD: + if (do_update(s, reqid, cops, p+l, len-l) == -1) + return -1; + break; + case NASTSTATS: + if (do_stats(s, reqid) == -1) + return -1; + break; + default: + return -1; + } + } + + return 0; +} + +static void +free_cops(client_opts *cops) +{ + if (cops == NULL) + return; + + close(cops->sock); + if (cops->opts != NULL) + free(cops->opts); + if (cops->opt_lk != NULL) + free(cops->opt_lk); + if (cops->tid != NULL) + free(cops->tid); + free(cops); +} + +static void * +io_looper(void *arg) +{ + client_opts *cops; + + (void)pthread_detach(pthread_self()); + cops = (client_opts *)arg; + + for (;;) { + ssize_t nbytes; + char buffer[1024]; + + nbytes = recv(cops->sock, buffer, sizeof(buffer), 0); + if (nbytes == -1) { + log_err("Couldn't read from socket: %s.", + strerror(errno)); + break; + } + if (nbytes == 0) { + /* Connection has been closed. Terminate. */ + log_info("Connection closed."); + break; + } + buffer[nbytes] = '\0'; + + /* Do command processing on the buffer. */ + if (process_cmd(cops->sock, cops, buffer, nbytes) == 1) + break; + } + + free_cops(cops); + return NULL; +} + +static void +set_default_opts(nast_options *opts) +{ + opts->use_qcache = NASTTRUE; + opts->use_localdb = NASTTRUE; + opts->fallthrough_async = NASTFALSE; + opts->always_fallthrough = NASTFALSE; + opts->fail_once = NASTFALSE; + opts->no_fallthrough = NASTFALSE; +} + +int +io_new(int s) +{ + client_opts *cops; + + log_info("Connection opened."); + + cops = malloc(sizeof(client_opts)); + if (cops == NULL) { + log_err("Couldn't allocate client option structure: %s.", + strerror(errno)); + return -1; + } + + /* Pre-set these. free_cops() relies on them being set. */ + cops->opts = NULL; + cops->opt_lk = NULL; + cops->sock = s; + cops->tid = NULL; + + cops->opts = malloc(sizeof(nast_options)); + if (cops->opts == NULL) { + log_err("Couldn't allocate client options structure: %s.", + strerror(errno)); + free_cops(cops); + return -1; + } + set_default_opts(cops->opts); + + cops->opt_lk = malloc(sizeof(rw_mutex_t)); + if (cops->opt_lk == NULL) { + log_err("Couldn't allocate client options mutex: %s.", + strerror(errno)); + free_cops(cops); + return -1; + } + + if (rw_mutex_new(cops->opt_lk)) { + log_err("Couldn't initialise client options mutex: %s.", + strerror(errno)); + free_cops(cops); + return -1; + } + + cops->tid = malloc(sizeof(thread_t)); + if (cops->tid == NULL) { + log_err("Couldn't allocate initial client thread: %s.", + strerror(errno)); + free_cops(cops); + return -1; + } + + if (thread_new(cops->tid, io_looper, cops)) { + log_err("Couldn't start initial looper thread: %s.", + strerror(errno)); + free_cops(cops); + return -1; + } + + return 0; +} diff --git a/server/.svn/text-base/nastdio.h.svn-base b/server/.svn/text-base/nastdio.h.svn-base new file mode 100644 index 0000000..e3375f6 --- /dev/null +++ b/server/.svn/text-base/nastdio.h.svn-base @@ -0,0 +1,14 @@ +/* $Id: nastdio.h,v 1.1 2000/09/13 20:21:34 shmit Exp $ */ + +#ifndef NASTDIO_H +#define NASTDIO_H + +struct _fieldent { + char *name; + short index; +}; +typedef struct _fieldent fieldent; + +int io_new(int sock); + +#endif diff --git a/server/.svn/text-base/periodic.c.svn-base b/server/.svn/text-base/periodic.c.svn-base new file mode 100644 index 0000000..9a94edb --- /dev/null +++ b/server/.svn/text-base/periodic.c.svn-base @@ -0,0 +1,118 @@ +#include "conf.h" +#include "cdb.h" +#include "log.h" +#include "memdb.h" +#include "mysqldb.h" +#include "thread.h" +#include "periodic.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +RCSID("$Id: periodic.c,v 1.9 2000/05/17 21:52:34 shmit Exp $"); + +struct _per_thread_t { + cond_t *cond; + thread_t *tid; +}; +typedef struct _per_thread_t per_thread_t; + +static void * +periodic_looper(void *arg) +{ + per_thread_t *self; + int count; + + self = (per_thread_t *)arg; + pthread_detach(pthread_self()); + + count = 0; + for (;;) { + struct timespec ts; + + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 1; + (void)cond_timedwait(self->cond, &ts); + + count++; + if (count == PERIODICITY) { + cdb_periodic(); + count = 0; + } + + cdb_collate(); + mysqldb_collate(); + memdb_collate(); + } + return NULL; +} + +void +periodic_delete(per_thread_t *thr) +{ + if (thr == NULL) + return; + + if (thr->cond) { + cond_destroy(thr->cond); + free(thr->cond); + thr->cond = NULL; + } + + if (thr->tid) { + free(thr->tid); + thr->tid = NULL; + } + free(thr); +} + +int +periodic_new() +{ + per_thread_t *per_thread; + int rc; + + per_thread = malloc(sizeof(per_thread_t)); + if (per_thread == NULL) { + log_err("Couldn't allocate periodic thread: %s.", + strerror(errno)); + return -1; + } + per_thread->cond = NULL; + per_thread->tid = NULL; + + per_thread->cond = malloc(sizeof(cond_t)); + if (per_thread->cond == NULL) { + log_err("Couldn't allocate periodic condition: %s.", + strerror(errno)); + periodic_delete(per_thread); + return -1; + } + + rc = cond_new(per_thread->cond); + if (rc) { + log_err("Couldn't initialise periodic condition: %s.", + strerror(rc)); + periodic_delete(per_thread); + return -1; + } + + per_thread->tid = malloc(sizeof(thread_t)); + if (per_thread->tid == NULL) { + log_err("Couldn't allocate periodic thread: %s.", + strerror(rc)); + periodic_delete(per_thread); + return -1; + } + + rc = thread_new(per_thread->tid, periodic_looper, per_thread); + if (rc) { + log_err("Couldn't start periodic thread: %s.", + strerror(rc)); + periodic_delete(per_thread); + return -1; + } + + return 0; +} diff --git a/server/.svn/text-base/periodic.h.svn-base b/server/.svn/text-base/periodic.h.svn-base new file mode 100644 index 0000000..835fd4a --- /dev/null +++ b/server/.svn/text-base/periodic.h.svn-base @@ -0,0 +1,8 @@ +/* $Id: periodic.h,v 1.2 2000/09/13 20:21:35 shmit Exp $ */ + +#ifndef NAST_PERIODIC_H +#define NAST_PERIODIC_H + +int periodic_new(); + +#endif diff --git a/server/.svn/text-base/thread.c.svn-base b/server/.svn/text-base/thread.c.svn-base new file mode 100644 index 0000000..95737d6 --- /dev/null +++ b/server/.svn/text-base/thread.c.svn-base @@ -0,0 +1,216 @@ +#include "conf.h" +#include "log.h" +#include "thread.h" + +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <sys/types.h> +#include <time.h> +#include <unistd.h> + +RCSID("$Id: thread.c,v 1.6 2000/03/21 19:18:24 shmit Exp $"); + +int +thread_new(thread_t *thread, void *(*thread_func)(void *), void *arg) +{ + int rc; + + thread->thread_func = thread_func; + rc = pthread_create(&thread->id, NULL, thread_func, arg); + if (rc != 0) { + log_err("Couldn't create thread: %s.\n", strerror(rc)); + return -1; + } + return 0; +} + +void +thread_kill(thread_t *thread) +{ +} + +int +thread_reload(thread_t *thread) +{ + return 0; +} + +int +mutex_new(mutex_t *lock) +{ + return pthread_mutex_init(lock, NULL); +} + +int +mutex_delete(mutex_t *lock) +{ + return pthread_mutex_destroy(lock); +} + +int +mutex_lock(mutex_t *lock) +{ + return pthread_mutex_lock(lock); +} + +int +mutex_unlock(mutex_t *lock) +{ + return pthread_mutex_unlock(lock); +} + +int +rw_mutex_new(rw_mutex_t *lock) +{ + int rc; + + rc = mutex_new(&lock->lock); + if (rc) + return rc; + rc = pthread_cond_init(&lock->read_sig, NULL); + if (rc) { + mutex_delete(&lock->lock); + return rc; + } + rc = pthread_cond_init(&lock->write_sig, NULL); + if (rc) { + mutex_delete(&lock->lock); + pthread_cond_destroy(&lock->read_sig); + return rc; + } + lock->state = 0; + lock->blocked_writers = 0; + + return 0; +} + +int +rw_mutex_read_lock(rw_mutex_t *lock) +{ + int rc; + + if (lock == NULL) + return EINVAL; + + rc = mutex_lock(&lock->lock); + if (rc) + return rc; + + /* Make sure the writers go before the readers. */ + while (lock->blocked_writers || lock->state < 0) { + rc = pthread_cond_wait(&lock->read_sig, &lock->lock); + if (rc) { + mutex_unlock(&lock->lock); + return rc; + } + } + lock->state++; + mutex_unlock(&lock->lock); + + return rc; +} + +int +rw_mutex_write_lock(rw_mutex_t *lock) +{ + int rc; + + if (lock == NULL) + return EINVAL; + + rc = mutex_lock(&lock->lock); + if (rc) + return rc; + + /* Wait for no readers on the lock. */ + while (lock->state != 0) { + lock->blocked_writers++; + rc = pthread_cond_wait(&lock->write_sig, &lock->lock); + lock->blocked_writers--; + if (rc) { + mutex_unlock(&lock->lock); + return rc; + } + } + lock->state = -1; + + mutex_unlock(&lock->lock); + return rc; +} + +int +rw_mutex_unlock(rw_mutex_t *lock) +{ + int rc; + + if (lock == NULL) + return EINVAL; + + rc = mutex_lock(&lock->lock); + if (rc) + return rc; + + if (lock->state > 0) { + /* We have an open read lock. */ + if (--lock->state == 0 && lock->blocked_writers) + rc = pthread_cond_signal(&lock->write_sig); + } else if (lock->state < 0) { + /* We have an open writer lock. */ + lock->state = 0; + if (lock->blocked_writers) + rc = pthread_cond_signal(&lock->write_sig); + else + rc = pthread_cond_broadcast(&lock->read_sig); + } else + rc = EINVAL; + + mutex_unlock(&lock->lock); + return rc; +} + +int +cond_new(cond_t *cond) +{ + int rc; + + if (cond == NULL) + return EINVAL; + + rc = pthread_cond_init(&cond->id, NULL); + if (rc) + return rc; + + rc = mutex_new(&cond->lock); + if (rc) + pthread_cond_destroy(&cond->id); + + return rc; +} + +int +cond_signal(cond_t *cond) +{ + return pthread_cond_signal(&cond->id); +} + +int +cond_wait(cond_t *cond) +{ + return pthread_cond_wait(&cond->id, &cond->lock); +} + +int +cond_timedwait(cond_t *cond, const struct timespec *abstime) +{ + return pthread_cond_timedwait(&cond->id, &cond->lock, abstime); +} + +int +cond_destroy(cond_t *cond) +{ + return pthread_cond_destroy(&cond->id); +} diff --git a/server/.svn/text-base/thread.h.svn-base b/server/.svn/text-base/thread.h.svn-base new file mode 100644 index 0000000..0aadef4 --- /dev/null +++ b/server/.svn/text-base/thread.h.svn-base @@ -0,0 +1,49 @@ +/* $Id: thread.h,v 1.5 2000/03/15 00:09:25 shmit Exp $ */ + +#ifndef THREAD_H +# define THREAD_H + +#include "conf.h" + +#include <pthread.h> + +typedef pthread_t thread_id; +typedef pthread_mutex_t mutex_t; + +struct _rwlock { + mutex_t lock; + int state; + pthread_cond_t read_sig; + pthread_cond_t write_sig; + int blocked_writers; +}; +typedef struct _rwlock rw_mutex_t; + +struct thread { + void *(*thread_func)(void *arg); + pthread_t id; +}; +typedef struct thread thread_t; + +struct cond { + pthread_cond_t id; + mutex_t lock; +}; +typedef struct cond cond_t; + +int thread_new(thread_t *thread, void *(*thread_func)(void *), void *arg); +void thread_kill(thread_t *thread); +int thread_reload(thread_t *thread); +int mutex_new(mutex_t *lock); +int mutex_lock(mutex_t *lock); +int mutex_unlock(mutex_t *lock); +int rw_mutex_new(rw_mutex_t *lock); +int rw_mutex_read_lock(rw_mutex_t *lock); +int rw_mutex_write_lock(rw_mutex_t *lock); +int rw_mutex_unlock(rw_mutex_t *lock); +int cond_new(cond_t *cond); +int cond_signal(cond_t *cond); +int cond_wait(cond_t *cond); +int cond_timedwait(cond_t *cond, const struct timespec *abstime); +int cond_destroy(cond_t *cond); +#endif diff --git a/server/Makefile b/server/Makefile new file mode 100644 index 0000000..0d26efe --- /dev/null +++ b/server/Makefile @@ -0,0 +1,32 @@ +# $Id: Makefile,v 1.17 2001/10/04 23:57:09 shmit Exp $ + +OBJS= array.o nastd.o nastdio.o cdb.o cdb_find.o cdb_hash.o \ + cdb_unpack.o fqm.o log.o md5.o memdb.o mysqldb.o periodic.o \ + thread.o ../libconfig/libconfig.a + +nastd: ${OBJS} + ${PURIFY} ${CC} -o $@ ${OBJS} ${LIBS} ${MYSQL_LIBS} + +# +# Dependencies +# +array.o: array.h log.h +nastd.o: ../include/nastipc.h ../include/config.h nastdio.h \ + cdb.h log.h memdb.h mysqldb.h periodic.h +nastdio.o: ../include/nastd.h ../include/nastipc.h array.h \ + nastdio.h cdb.h fqm.h log.h memdb.h mysqldb.h thread.h +cdb.o: ../include/config.h array.h nastdio.h cdbpriv.h log.h \ + memdb.h thread.h +cdb_find.o: cdbpriv.h +cdb_hash.o: cdbpriv.h +cdb_unpack.o: cdbpriv.h +fqm.o: fqm.h log.h thread.h +log.o: log.h +md5.o: log.h md5.h +memdb.o: ../include/config.h array.h log.h md5.h memdb.h thread.h +mysqldb.o: array.h nastdio.h log.h mysqldb.h +periodic.o: cdb.h log.h thread.h periodic.h +thread.o: thread.h + +MKDIR= ../Makefiles +include ${MKDIR}/build diff --git a/server/array.c b/server/array.c new file mode 100644 index 0000000..65766de --- /dev/null +++ b/server/array.c @@ -0,0 +1,149 @@ +#include "conf.h" +#include "array.h" +#include "log.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +RCSID("$Id: array.c,v 1.10 2000/10/17 23:38:27 shmit Exp $"); + +string_t * +string_new(int slen, char *strdata) +{ + string_t *tmp; + + tmp = malloc(sizeof(string_t)); + if (tmp == NULL) { + log_err("Couldn't allocate data for string: %s.", + strerror(errno)); + return NULL; + } + + tmp->str = malloc(slen * sizeof(char *)); + if (tmp->str == NULL) { + log_err("Couldn't allocate string data: %s.", + strerror(errno)); + return NULL; + } + memcpy(tmp->str, strdata, slen); + tmp->strlen = slen; + + return tmp; +} + +void +string_delete(string_t *string) +{ + if (string == NULL) + return; + + if (string->str != NULL) + free(string->str); + string->strlen = 0; + string->str = NULL; + free(string); +} + +array_t * +array_new() +{ + array_t *tmp; + + tmp = malloc(sizeof(array_t)); + if (tmp == NULL) + return NULL; + + tmp->nitems = 0; + tmp->items = NULL; + return tmp; +} + +void +array_delete(array_t *aa) +{ + int i; + + if (aa == NULL) + return; + + for (i = 0; i < aa->nitems; i++) + string_delete(aa->items[i]); + free(aa->items); + aa->items = NULL; + free(aa); +} + +int +va_array_add(array_t *aa, va_list ap) +{ + const int GRANULARITY = 10; + int slen; + char *s; + + slen = va_arg(ap, int); + if (slen != ARRTERM) + s = va_arg(ap, char *); + else + s = NULL; + while (s) { + if (aa->nitems % GRANULARITY == 0) { + aa->items = realloc(aa->items, sizeof(string_t *) * + (GRANULARITY + aa->nitems)); + if (aa->items == NULL) + return -1; + } + aa->nitems++; + aa->items[aa->nitems-1] = string_new(slen, s); + if (aa->items[aa->nitems-1] == NULL) + return -1; + slen = va_arg(ap, int); + if (slen != ARRTERM) + s = va_arg(ap, char *); + else + s = NULL; + } + + return 0; +} + +int +array_add(array_t *aa, ...) +{ + va_list ap; + int rc; + + va_start(ap, aa); + rc = va_array_add(aa, ap); + va_end(ap); + + return rc; +} + +int +array_dup(array_t *dst, array_t *src) +{ + int i; + + if (dst == NULL) + return -1; + + dst->nitems = src->nitems; + dst->items = malloc(dst->nitems * sizeof(string_t *)); + if (dst->items == NULL) { + log_err("Couldn't allocate dup array items list: %s.", + strerror(errno)); + return -1; + } + + for (i = 0; i < dst->nitems; i++) { + dst->items[i] = string_new(src->items[i]->strlen, + src->items[i]->str); + if (dst->items[i] == NULL) { + dst->nitems = i; + return -1; + } + } + + return 0; +} diff --git a/server/array.h b/server/array.h new file mode 100644 index 0000000..83b4ee1 --- /dev/null +++ b/server/array.h @@ -0,0 +1,31 @@ +/* $Id: array.h,v 1.4 2000/10/17 23:38:27 shmit Exp $ */ + +#ifndef ARRAY_H +#define ARRAY_H + +#include <stdarg.h> + +#define ARRTERM -1 + +struct _string_t { + char *str; + int strlen; +}; +typedef struct _string_t string_t; + +struct _array_t { + int nitems; + string_t **items; +}; +typedef struct _array_t array_t; + +string_t *string_new(int slen, char *strdata); +void string_delete(string_t *string); + +array_t *array_new(); +void array_delete(array_t *array); +int va_array_add(array_t *aa, va_list ap); +int array_add(array_t *aa, ...); +int array_dup(array_t *dst, array_t *src); + +#endif diff --git a/server/cdb.c b/server/cdb.c new file mode 100644 index 0000000..4f55d03 --- /dev/null +++ b/server/cdb.c @@ -0,0 +1,324 @@ +#include "conf.h" +#include "config.h" +#include "array.h" +#include "nastdio.h" +#include "cdbpriv.h" +#include "log.h" +#include "memdb.h" +#include "thread.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> + +RCSID("$Id: cdb.c,v 1.64 2001/10/19 22:28:07 shmit Exp $"); + +time_t cdb_mtime; + +static char *memcdb = NULL; +static rw_mutex_t *cdb_lk = NULL; +static uint32_t cdb_len = 0; + +/* + * Exportable symbols - the CDB file is authoritative for them, so they + * come from here, but nastdio.c is their consumer. + */ +char db_key[1024]; +char db_dbn[1024]; +char db_tbl[1024]; +fieldent *db_fields = NULL; +char db_sep; +short db_fieldcount = 0; + +static int sec_c; +static float onemin_c, fivemin_c, fifteenmin_c; + +static int +cdb_findbykey(char *mcdb, int len, const char *key, int keylen, + char **data, int *dlen) +{ + if (cdb_find(mcdb, len, key, keylen, data, dlen) != 1) + return -1; + + return 0; +} + +int +cdb_new() +{ + char *newcdb; + char *p, *s_p, *e_p; + fieldent *newfields; + char buffer[1024]; + char cdbfields_s[1024], newkey[1024], newtbl[1024], newdbn[1024]; + char newsep; + struct stat sb; + int i, fieldslen, newfieldcount; + int fd; + size_t len; + + log_info("Initialising CDB interface."); + + sec_c = 0; + onemin_c = fivemin_c = fifteenmin_c = 0; + + if (!cdb_lk) { + cdb_lk = malloc(sizeof(rw_mutex_t)); + if (!cdb_lk) { + log_err("Couldn't allocate CDB mutex: %s.", + strerror(errno)); + return -1; + } + if (rw_mutex_new(cdb_lk)) { + log_err("Couldn't initialse CDB mutex: %s.", + strerror(errno)); + return -1; + } + } + + snprintf(buffer, sizeof(buffer), "%s/%s", + config.nast_dir, config.nast_cdb_file); + fd = open(buffer, O_RDONLY); + if (fd == -1) { + log_err("Couldn't open %s: %s.", buffer, strerror(errno)); + return -1; + } + + if (fstat(fd, &sb) == -1) { + log_err("Couldn't stat %s: %s.", buffer, strerror(errno)); + return -1; + } + len = sb.st_size; + + newcdb = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); + if (newcdb == MAP_FAILED) { + log_err("Couldn't mmap %s: %s.", buffer, strerror(errno)); + return -1; + } + + (void)close(fd); + + /* Get the key out of the CDB, so clients know how to search. */ + if (cdb_findbykey(newcdb, len, "_KEY_", strlen("_KEY_"), + &p, &i) == -1) { + log_err("Couldn't find `_KEY_' in the CDB."); + munmap(newcdb, len); + return -1; + } + + if (i > sizeof(newkey)) { + log_err("Couldn't copy key information from the CDB."); + munmap(newcdb, len); + return -1; + } + memcpy(newkey, p, i); + newkey[i] = '\0'; + + /* Get the dbname out of the CDB, so mysql knows which db to use. */ + if (cdb_findbykey(newcdb, len, "_DB_", strlen("_DB_"), &p, &i) == -1) { + log_err("Warning: Couldn't find `_DB_' in the CDB."); + strncpy(newdbn, DBNAME, sizeof(newdbn)); + } else { + if (i > sizeof(newdbn)) { + log_err("Couldn't copy database information " + "from the CDB."); + munmap(newcdb, len); + return -1; + } + memcpy(newdbn, p, i); + newdbn[i] = '\0'; + } + + /* Get the table out of the CDB, so mysql knows which to use. */ + if (cdb_findbykey(newcdb, len, "_TABLE_", strlen("_TABLE_"), + &p, &i) == -1) { + log_err("Warning: Couldn't find `_TABLE_' in the CDB."); + strncpy(newtbl, DBTBL, sizeof(newtbl)); + } else { + if (i > sizeof(newtbl)) { + log_err("Couldn't copy table information " + "from the CDB."); + munmap(newcdb, len); + return -1; + } + memcpy(newtbl, p, i); + newtbl[i] = '\0'; + } + + /* Get the delimiter out of the CDB file. */ + if (cdb_findbykey(newcdb, len, "_DELIM_", strlen("_DELIM_"), + &p, &i) == -1) { + log_info("Couldn't find `_DELIM_' in the CDB. Using default."); + newsep = ':'; + } else + newsep = *p; + + /* Now get the column names. */ + if (cdb_findbykey(newcdb, len, "_VALUES_", strlen("_VALUES_"), + &p, &i) == -1) { + log_err("Couldn't find `_VALUES_' in the CDB."); + munmap(newcdb, len); + return -1; + } + if (i >= sizeof(cdbfields_s)) { + log_err("Couldn't copy value information from the CDB."); + munmap(newcdb, len); + return -1; + } + memcpy(cdbfields_s, p, i); + cdbfields_s[i] = '\0'; + fieldslen = strlen(cdbfields_s); + + /* Fill out cdbfields with an array of field names. */ + newfieldcount = 0; + for (i = 0; i <= fieldslen; i++) { + if (cdbfields_s[i] == newsep || i == fieldslen) + newfieldcount++; + } + + newfields = malloc(sizeof(fieldent) * newfieldcount); + if (newfields == NULL) { + log_err("Couldn't allocate space for field array: %s.", + strerror(errno)); + munmap(newcdb, len); + return -1; + } + + s_p = cdbfields_s; + for (i = 0; i < newfieldcount; i++) { + for (e_p = s_p; *e_p != newsep && *e_p != '\0'; e_p++); + + newfields[i].index = i; + newfields[i].name = malloc(e_p - s_p + 1*sizeof(char)); + if (newfields[i].name == NULL) { + /* XXX: clean up. */ + log_err("Couldn't allocate space for field: %s.", + strerror(errno)); + munmap(newcdb, len); + return -1; + } + memcpy(newfields[i].name, s_p, e_p - s_p); + newfields[i].name[e_p - s_p] = '\0'; + s_p = e_p + 1; + } + + rw_mutex_write_lock(cdb_lk); + if (memcdb) + munmap(memcdb, cdb_len); + memcdb = newcdb; + cdb_len = (uint32_t)len; + cdb_mtime = sb.st_mtime; + + memcpy(db_dbn, newdbn, sizeof(db_dbn)); + memcpy(db_tbl, newtbl, sizeof(db_tbl)); + memcpy(db_key, newkey, sizeof(db_key)); + if (db_fields) + free(db_fields); + db_fields = newfields; + db_sep = newsep; + db_fieldcount = newfieldcount; + rw_mutex_unlock(cdb_lk); + + log_info("CDB interface initialised."); + return 0; +} + +int +cdb_get(const char *key, int keylen, array_t *aa) +{ + char *s_p, *e_p; + char *data; + int dlen; + + rw_mutex_read_lock(cdb_lk); + if (cdb_findbykey(memcdb, cdb_len, key, keylen, &data, &dlen) == -1) { + rw_mutex_unlock(cdb_lk); + return -1; + } + + sec_c++; + + s_p = data; e_p = data; + while (e_p <= data+dlen) { + if (*e_p == db_sep || e_p == data+dlen) { + if (array_add(aa, e_p-s_p, s_p, ARRTERM) == -1) { + rw_mutex_unlock(cdb_lk); + return -1; + } + s_p = e_p + 1; + } + e_p++; + } + + rw_mutex_unlock(cdb_lk); + return 0; +} + +void +cdb_periodic() +{ + char buffer[1024]; + struct stat sb; + + snprintf(buffer, sizeof(buffer), "%s/%s", + config.nast_dir, config.nast_cdb_file); + if (stat(buffer, &sb) == -1) { + log_err("PERIODIC: Couldn't stat %s: %s.\n", buffer, + strerror(errno)); + return; + } + + if (sb.st_size == 0) { + log_err("PERIODIC: WARNING! CDB file is empty!"); + return; + } + + if (cdb_mtime < sb.st_mtime) { + log_info("PERIODIC: CDB file changed, reloading.\n"); + (void)cdb_new(); + + /* + * Turned off, as now entries are time stamped and + * auto-expire when the cdb file is updated. + */ + /* (void)memdb_new(); */ + return; + } +} + +int +cdb_stats(array_t *statarr) +{ + char buffer[512]; + char tbuff[512]; + struct tm res; + + snprintf(buffer, sizeof(buffer), "CDB: %.2f, %.2f, %.2f", + onemin_c, fivemin_c, fifteenmin_c); + if (array_add(statarr, strlen(buffer), buffer, ARRTERM) == -1) + return -1; + + /* Convert CDB mtime into a string. */ + (void)localtime_r(&cdb_mtime, &res); + strftime(tbuff, sizeof(tbuff), "%Y%m%d %H:%M:%S", &res); + + snprintf(buffer, sizeof(buffer), "CDB: last updated: %s", + tbuff); + return array_add(statarr, strlen(buffer), buffer, ARRTERM); +} + +void +cdb_collate() +{ + onemin_c = ((onemin_c * 59) + sec_c) / 60; + fivemin_c = ((fivemin_c * 299) + sec_c) / 300; + fifteenmin_c = ((fifteenmin_c * 899) + sec_c) / 900; + sec_c = 0; +} diff --git a/server/cdb.h b/server/cdb.h new file mode 100644 index 0000000..0da14df --- /dev/null +++ b/server/cdb.h @@ -0,0 +1,15 @@ +/* $Id: cdb.h,v 1.11 2000/05/17 19:32:58 shmit Exp $ */ + +#ifndef CDB_H +#define CDB_H + +#include "array.h" + +int cdb_new(); +int cdb_get(const char *key, int keylen, array_t *dstarr); +void cdb_periodic(); + +int cdb_stats(array_t *statarr); +void cdb_collate(); + +#endif diff --git a/server/cdb_find.c b/server/cdb_find.c new file mode 100644 index 0000000..2fc2bcf --- /dev/null +++ b/server/cdb_find.c @@ -0,0 +1,121 @@ +#include "cdbpriv.h" + +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +RCSID("$Id: cdb_find.c,v 1.2 2000/02/29 19:31:33 shmit Exp $"); + +static int +cdb_bread(char **ptr, char *endptr, char *buf, unsigned int len) +{ + if ((*ptr)+len > endptr) { + errno = EIO; + return -1; + } + + memcpy(buf, *ptr, len); + *ptr += len; + return 0; +} + +static int +match(char **ptr, char *endptr, const char *key, unsigned int len) +{ + char buf[32]; + int n; + int i; + + n = sizeof(buf); + if (n > len) + n = len; + + while (len > 0) { + if (cdb_bread(ptr, endptr, buf, n) == -1) + return -1; + + for (i = 0; i < n; ++i) + if (buf[i] != key[i]) + return 0; + key += n; + len -= n; + } + + return 1; +} + +int +cdb_find(char *buff, off_t bufflen, const char *key, int len, + char **ret, uint32_t *retlen) +{ + char *cur, *end; + char packbuf[8]; + uint32_t pos; + uint32_t h; + uint32_t lenhash; + uint32_t h2; + uint32_t loop; + uint32_t poskd; + + cur = buff; + end = buff + bufflen; + + h = cdb_hash(key, len); + + pos = 8 * (h & 255); + cur += pos; + if (cur > end) { + errno = EIO; + return -1; + } + + if (cdb_bread(&cur, end, packbuf, 8) == -1) + return -1; + + pos = cdb_unpack(packbuf); + lenhash = cdb_unpack(packbuf + 4); + + if (!lenhash) return 0; + h2 = (h >> 8) % lenhash; + + for (loop = 0; loop < lenhash; ++loop) { + cur = buff + (pos + 8 * h2); + if (cur > end) { + errno = EIO; + return -1; + } + if (cdb_bread(&cur, end, packbuf, 8) == -1) + return -1; + poskd = cdb_unpack(packbuf + 4); + if (!poskd) + return 0; + + if (cdb_unpack(packbuf) == h) { + cur = buff + poskd; + if (cur > end) { + errno = EIO; + return -1; + } + if (cdb_bread(&cur, end, packbuf, 8) == -1) + return -1; + if (cdb_unpack(packbuf) == len) { + switch(match(&cur, end, key, len)) { + case -1: + return -1; + case 1: + *retlen = cdb_unpack(&packbuf[4]); + *ret = cur; + return 1; + } + } + } + if (++h2 == lenhash) + h2 = 0; + } + + return 0; +} diff --git a/server/cdb_hash.c b/server/cdb_hash.c new file mode 100644 index 0000000..b664ba9 --- /dev/null +++ b/server/cdb_hash.c @@ -0,0 +1,18 @@ +#include "conf.h" +#include "cdbpriv.h" + +RCSID("$Id: cdb_hash.c,v 1.2 2000/02/29 19:31:33 shmit Exp $"); + +uint32_t +cdb_hash(const unsigned char *buf, unsigned int len) +{ + uint32_t h; + + h = 5381; + while (len) { + --len; + h += (h << 5); + h ^= (uint32_t)*buf++; + } + return h; +} diff --git a/server/cdb_unpack.c b/server/cdb_unpack.c new file mode 100644 index 0000000..14a71b9 --- /dev/null +++ b/server/cdb_unpack.c @@ -0,0 +1,16 @@ +#include "conf.h" +#include "cdbpriv.h" + +RCSID("$Id: cdb_unpack.c,v 1.2 2000/02/29 19:31:33 shmit Exp $"); + +uint32_t +cdb_unpack(unsigned char *buf) +{ + uint32_t num; + + num = buf[3]; num <<= 8; + num += buf[2]; num <<= 8; + num += buf[1]; num <<= 8; + num += buf[0]; + return num; +} diff --git a/server/cdbpriv.h b/server/cdbpriv.h new file mode 100644 index 0000000..cc398a8 --- /dev/null +++ b/server/cdbpriv.h @@ -0,0 +1,15 @@ +/* $Id: cdbpriv.h,v 1.2 2000/02/29 19:15:28 shmit Exp $ */ + +#ifndef CDBPRIV_H +#define CDBPRIV_H + +#include "conf.h" + +#include <sys/types.h> + +int cdb_find(char *buff, off_t bufflen, const char *key, int len, + char **ret, uint32_t *retlen); +uint32_t cdb_hash(const unsigned char *buff, unsigned int len); +uint32_t cdb_unpack(unsigned char *buff); + +#endif diff --git a/server/fqm.c b/server/fqm.c new file mode 100644 index 0000000..73c9e54 --- /dev/null +++ b/server/fqm.c @@ -0,0 +1,448 @@ +#include "conf.h" +#include "fqm.h" +#include "log.h" +#include "mysqldb.h" +#include "thread.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +RCSID("$Id: fqm.c,v 1.33 2001/10/29 11:17:13 shmit Exp $"); + +/* Global Variables */ +fqm_t *fqm; + +request_t * +req_new(int sock, short reqid, REQHANDLER((*req_handler)), + const char *reqstr, int reqlen) +{ + request_t *tmp; + + tmp = malloc(sizeof(request_t)); + if (tmp == NULL) { + log_err("Couldn't allocate request: %s.", strerror(errno)); + return NULL; + } + + tmp->req = malloc((reqlen + 1) * sizeof(char)); + if (tmp->req == NULL) { + log_err("Couldn't allocate request string: %s.", + strerror(errno)); + req_delete(tmp); + return NULL; + } + memcpy(tmp->req, reqstr, reqlen); + tmp->req[reqlen] = '\0'; + tmp->sock = sock; + tmp->reqid = reqid; + tmp->req_handler = req_handler; + + return tmp; +} + +void +req_delete(request_t *req) +{ + if (req) { + if (req->req) + free(req->req); + free(req); + } +} + +static request_t * +fqm_pop(reqthread_t *req) +{ + fqm_t *fqm; + request_t *p; + + if (req == NULL || req->fqm == NULL) { + mutex_unlock(&req->fqm->q_cond->lock); + return NULL; + } + fqm = req->fqm; + + /* Wait for something to arrive on the queue. */ + mutex_lock(&req->fqm->q_cond->lock); + req->status = IDLE; + + if (fqm->sreq == NULL) + cond_wait(fqm->q_cond); + + /* Something waiting on the queue. Scarf it off and unlock. */ + p = fqm->sreq; + if (p == NULL) { + mutex_unlock(&fqm->q_cond->lock); + return NULL; + } + fqm->sreq = fqm->sreq->next; + fqm->nitems--; + req->status = BUSY; + mutex_unlock(&fqm->q_cond->lock); + + p->next = NULL; + return p; +} + +static void * +fqm_popper(void *arg) +{ + reqthread_t *self; + request_t *req; + + /* Detach this thread. */ + (void)pthread_detach(pthread_self()); + + self = (reqthread_t *)arg; + for (;;) { + req = fqm_pop(self); + + /* + * Check to see if we were told to die. If we were, + * do so. + * Note: there's the possibility for the dropping of + * a request here. Que sera sera. + */ + if (self->dieflag) + break; + if (req == NULL) + continue; + if (req->req_handler(req, self) == -1) + log_info("Couldn't handle request"); + req_delete(req); + } + + log_info("Got a kill flag; dying off."); + mutex_lock(&self->fqm->t_cond->lock); + self->status = NOALLOC; + cond_signal(self->fqm->t_cond); + mutex_unlock(&self->fqm->t_cond->lock); + return NULL; +} + +static reqthread_t * +fqm_thr_new(fqm_t *fqm) +{ + reqthread_t *tmp; + + tmp = malloc(sizeof(reqthread_t)); + if (tmp == NULL) { + log_err("Couldn't allocate fallthrough thread: %s.", + strerror(errno)); + return NULL; + } + + tmp->arg = NULL; + tmp->fqm = fqm; + tmp->dieflag = 0; + tmp->status = NOALLOC; + + tmp->tid = malloc(sizeof(thread_t)); + if (tmp->tid == NULL) { + log_err("Couldn't allocate fallthrough thread: %s.", + strerror(errno)); + free(tmp); + return NULL; + } + + if (thread_new(tmp->tid, fqm_popper, tmp)) { + log_err("Couldn't start fallthrough thread: %s.", + strerror(errno)); + free(tmp->tid); + tmp->tid = NULL; + free(tmp); + return NULL; + } + tmp->status = IDLE; + + return tmp; +} + +static int +fqm_thr_wait(fqm_t *fqm) +{ + int deadthreads; + int i; + + deadthreads = 0; + + for (i = 0; i < fqm->maxitems; i++) { + if (fqm->tids[i] && fqm->tids[i]->status == NOALLOC) { + mysqldb_connect_close(fqm->tids[i]->arg); + if (fqm->tids[i]->tid != NULL) + free(fqm->tids[i]->tid); + free(fqm->tids[i]); + fqm->tids[i] = NULL; + deadthreads++; + } + } + + return deadthreads; +} + +fqm_t * +fqm_new(int maxitems) +{ + fqm_t *tmp; + int i; + + tmp = malloc(sizeof(fqm_t)); + if (tmp == NULL) { + log_err("Couldn't create fallthrough queue manager: %s.", + strerror(errno)); + return NULL; + } + + tmp->q_cond = NULL; + tmp->t_cond = NULL; + tmp->tids = NULL; + tmp->sreq = NULL; tmp->ereq = NULL; + tmp->maxitems = 0; + tmp->nitems = 0; + + tmp->q_cond = malloc(sizeof(cond_t)); + if (tmp->q_cond == NULL) { + log_err("Couldn't allocate queue condition variable: %s.", + strerror(errno)); + fqm_delete(tmp); + return NULL; + } + + if (cond_new(tmp->q_cond)) { + log_err("Couldn't initialise queue condition variable: %s.", + strerror(errno)); + fqm_delete(tmp); + return NULL; + } + + tmp->t_cond = malloc(sizeof(cond_t)); + if (tmp->t_cond == NULL) { + log_err("Couldn't allocate queue destroy condition: %s.", + strerror(errno)); + fqm_delete(tmp); + return NULL; + } + + if (cond_new(tmp->t_cond)) { + log_err("Couldn't initialise queue destroy condition: %s.", + strerror(errno)); + fqm_delete(tmp); + return NULL; + } + + tmp->tids = malloc(maxitems * sizeof(reqthread_t *)); + if (tmp->tids == NULL) { + log_err("Couldn't allocate fallthrough queue threads: %s.", + strerror(errno)); + fqm_delete(tmp); + return NULL; + } + + /* Init these so fqm_delete won't break. */ + for (i = 0; i < maxitems; i++) + tmp->tids[i] = NULL; + + /* We cannot adjust max items while threads are busy, so lock. */ + mutex_lock(&tmp->q_cond->lock); + for (i = 0; i < maxitems; i++) { + tmp->tids[i] = fqm_thr_new(tmp); + if (tmp->tids[i] == NULL) { + mutex_unlock(&tmp->q_cond->lock); + fqm_delete(tmp); + return NULL; + } + tmp->maxitems++; + } + mutex_unlock(&tmp->q_cond->lock); + + /* XXX: this may need a lock. */ + fqm = tmp; + return tmp; +} + +/* + * Make sure all threads in this fqm are idle. This is an expensive + * operation, but that's okay, since this code should only be run when + * a client has closed the connection, so we can take as long as we want. + * + * The queue is locked when coming in to this routine and leaving it. + */ +void +verify_idle_threads(fqm_t *fqm) +{ + int i, busy_thread; + + do { + busy_thread = 0; + for (i = 0; i < fqm->maxitems; i++) { + if (fqm->tids[i]->status == BUSY) + busy_thread = 1; + } + + /* + * This is the shitty part. + * We unlock the queue and sleep for a bit to give other + * threads a chance to finish what they're doing. + */ + if (busy_thread) { + mutex_unlock(&fqm->q_cond->lock); + sleep(1); + mutex_lock(&fqm->q_cond->lock); + } + } while (busy_thread); +} + +void +fqm_delete(fqm_t *fqm) +{ + int i; + + if (fqm->tids) { + /* Tell all threads to quit. */ + for (i = 0; i < fqm->maxitems; i++) { + if (fqm->tids[i] != NULL) + fqm->tids[i]->dieflag = 1; + } + + /* + * Lock queue waiting condition to ensure that no + * threads miss this signal. The threads MUST be idle + * in order to guarantee this signal is recieved. + */ + mutex_lock(&fqm->q_cond->lock); + verify_idle_threads(fqm); + pthread_cond_broadcast(&fqm->q_cond->id); + mutex_unlock(&fqm->q_cond->lock); + + /* Now wait for them to die off. */ + i = 0; + while (i < fqm->maxitems) { + mutex_lock(&fqm->t_cond->lock); + i += fqm_thr_wait(fqm); + if (i < fqm->maxitems) + cond_wait(fqm->t_cond); + mutex_unlock(&fqm->t_cond->lock); + } + free(fqm->tids); + fqm->tids = NULL; + } + + /* + * At this point all fqm threads should be dead. + */ + if (fqm->t_cond) { + (void)cond_destroy(fqm->t_cond); + free(fqm->t_cond); + fqm->t_cond = NULL; + } + + if (fqm->q_cond) { + (void)cond_destroy(fqm->q_cond); + free(fqm->q_cond); + fqm->q_cond = NULL; + } + + free(fqm); +} + +int +fqm_changemaxitems(fqm_t *fqm, int maxitems) +{ + reqthread_t **new_tidpool; + int i, j; + + /* + * This code broken. Silently fail here. + */ + return 0; + + if (fqm->maxitems == maxitems) + return 0; + + mutex_lock(&fqm->q_cond->lock); + /* + * Make sure all threads are busy. We can't go changing + * data under them. + */ + verify_idle_threads(fqm); + new_tidpool = malloc(maxitems * sizeof(reqthread_t *)); + if (new_tidpool == NULL) { + mutex_unlock(&fqm->q_cond->lock); + log_err("Couldn't allocate new FQM thread pool: %s.", + strerror(errno)); + return -1; + } + + /* Compress old TID pool. */ + for (j = 0, i = 0; i < fqm->maxitems && j < maxitems; i++) { + if (fqm->tids[i]->status != NOALLOC) { + new_tidpool[j] = fqm->tids[i]; + j++; + } + } + + if (fqm->maxitems < maxitems) { + /* Add more threads. */ + mutex_lock(&fqm->q_cond->lock); + for (i = fqm->maxitems; i < maxitems; i++) { + new_tidpool[i] = fqm_thr_new(fqm); + if (new_tidpool[i] == NULL) { + free(new_tidpool); + mutex_unlock(&fqm->q_cond->lock); + return -1; + } + } + mutex_unlock(&fqm->q_cond->lock); + } else if (fqm->maxitems > maxitems) { + /* Kill some threads. */ + int deadthreads; + + /* Tell them to die, then wake 'em up. */ + for (i = maxitems; i < fqm->maxitems; i++) + fqm->tids[i]->dieflag = 1; + pthread_cond_broadcast(&fqm->q_cond->id); + + deadthreads = 0; + while (deadthreads < fqm->maxitems - maxitems) { + mutex_lock(&fqm->t_cond->lock); + deadthreads += fqm_thr_wait(fqm); + if (deadthreads < fqm->maxitems - maxitems) + cond_wait(fqm->t_cond); + mutex_unlock(&fqm->t_cond->lock); + } + } + + free(fqm->tids); + fqm->tids = new_tidpool; + fqm->maxitems = maxitems; + mutex_unlock(&fqm->q_cond->lock); + return 0; +} + +int +fqm_push(fqm_t *fqm, request_t *req) +{ + if (fqm->nitems == fqm->maxitems) { + log_err("Too many items on the request queue."); + return -1; + } + + /* Lock the queue and add the item. */ + mutex_lock(&fqm->q_cond->lock); + + req->next = NULL; + if (fqm->sreq == NULL) + fqm->sreq = req; + else + fqm->ereq->next = req; + fqm->ereq = req; + fqm->nitems++; + + /* Unlock the queue and signal that there's an item on it. */ + cond_signal(fqm->q_cond); + mutex_unlock(&fqm->q_cond->lock); + return 0; +} diff --git a/server/fqm.h b/server/fqm.h new file mode 100644 index 0000000..c3c27df --- /dev/null +++ b/server/fqm.h @@ -0,0 +1,50 @@ +/* $Id: fqm.h,v 1.9 2000/11/08 19:50:24 shmit Exp $ */ + +#ifndef FQM_H +#define FQM_H + +#include "thread.h" + +#define REQHANDLER(func) int func(struct _request_t *req, reqthread_t *self) + +enum _status_t { IDLE, BUSY, NOALLOC }; +typedef enum _status_t status_t; + +struct _reqthread_t { + struct _fqm_t *fqm; + thread_t *tid; + void *arg; + int dieflag; + status_t status; +}; +typedef struct _reqthread_t reqthread_t; + +struct _request_t { + REQHANDLER((*req_handler)); + char *req; + int sock; + short reqid; + struct _request_t *next; +}; +typedef struct _request_t request_t; + +struct _fqm_t { + cond_t *q_cond; + cond_t *t_cond; + request_t *sreq, *ereq; + reqthread_t **tids; + int maxitems; + int nitems; +}; +typedef struct _fqm_t fqm_t; + +request_t *req_new(int sock, short reqid, REQHANDLER((*req_handler)), + const char *reqstr, int reqlen); +void req_delete(request_t *req); + +fqm_t *fqm_new(int maxitems); +void fqm_delete(fqm_t *fqm); +int fqm_changemaxitems(fqm_t *fqm, int maxitems); +int fqm_push(fqm_t *fqm, request_t *req); + +#endif diff --git a/server/log.c b/server/log.c new file mode 100644 index 0000000..612156d --- /dev/null +++ b/server/log.c @@ -0,0 +1,99 @@ +#include "conf.h" +#include "log.h" + +#include <pthread.h> +#include <stdarg.h> +#include <stdio.h> +#include <sys/time.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> + +RCSID("$Id: log.c,v 1.8 2000/11/13 18:47:17 shmit Exp $"); + +extern char *progname; + +#if 0 +FILE *logf = NULL; +#endif + +static void log_priority(int priority, const char *fmt, va_list args); + +/* + * Log a message with a given priority. + */ +void +log_priority(int priority, const char *fmt, va_list args) +{ + char lbuff[1024]; +#if 0 + char tbuff[256]; + struct tm timeptr; + time_t tloc; +#endif + + (void)snprintf(lbuff, sizeof(lbuff), + "[tid: %d] %s", (int)pthread_self(), fmt); + vsyslog(priority, lbuff, args); + +#if 0 + tloc = time(0); + (void)localtime_r(&tloc, &timeptr); + (void)strftime(tbuff, sizeof(tbuff), "%Y-%h-%d %H:%M:%S", &timeptr); + (void)snprintf(lbuff, sizeof(lbuff), "%s %s[%d:%d] %s\n", + tbuff, progname, getpid(), (int)pthread_self(), fmt); + (void)vfprintf(logf, lbuff, args); +#endif +} + +/* + * Log an error message. + */ +void +log_err(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + log_priority(LOG_ERR, fmt, ap); + va_end(ap); +} + +/* + * Log a warning message. + */ +void +log_warn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + log_priority(LOG_WARNING, fmt, ap); + va_end(ap); +} + +/* + * Log an informational message. + */ +void +log_info(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + log_priority(LOG_INFO, fmt, ap); + va_end(ap); +} + +/* + * Initialize logging facilites. + */ +void +log_open() +{ + openlog(progname, LOG_PID|LOG_PERROR, LOG_DAEMON); + +#if 0 + logf = fopen("/home/shmit/var/log/nastd.log", "a+"); +#endif +} diff --git a/server/log.h b/server/log.h new file mode 100644 index 0000000..9aff53a --- /dev/null +++ b/server/log.h @@ -0,0 +1,11 @@ +/* $Id: log.h,v 1.1 2000/02/29 00:32:12 shmit Exp $ */ + +#ifndef LOG_H +# define LOG_H + +void log_open(); +void log_err(const char *fmt, ...); +void log_warn(const char *fmt, ...); +void log_info(const char *fmt, ...); + +#endif /* LOG_H */ diff --git a/server/md5.c b/server/md5.c new file mode 100644 index 0000000..b24f966 --- /dev/null +++ b/server/md5.c @@ -0,0 +1,308 @@ +/* + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. + * All rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD5 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD5 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +#include "conf.h" +#include "log.h" +#include "md5.h" + +#include <string.h> + +RCSID("$Id: md5.c,v 1.2 2000/03/27 22:23:25 shmit Exp $"); + +/* Constants for MD5Transform routine. */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform(uint32_t *, const unsigned char *); +static void Encode(unsigned char *, uint32_t *, unsigned int, int ouputlen); +static void Decode(uint32_t *, const unsigned char *, unsigned int); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* + * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + * Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +void +md5_calc(unsigned char *output, const unsigned char *input, unsigned int inlen, + int outputlen) +{ + MD5_CTX context; + + MD5Init(&context); + MD5Update(&context, input, inlen); + MD5Final(output, &context, outputlen); +} + +/* + * MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void +MD5Init(MD5_CTX *context) +{ + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* + * MD5 block update operation. Continues an MD5 message-digest + * operation, processing another message block, and updating the + * context. + */ +void +MD5Update(MD5_CTX *context, const unsigned char *input, unsigned int inputLen) +{ + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((uint32_t)inputLen << 3)) < + ((uint32_t)inputLen << 3)) + context->count[1]++; + context->count[1] += ((uint32_t)inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. */ + if (inputLen >= partLen) { + memcpy(&context->buffer[index], input, partLen); + MD5Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } else + i = 0; + + /* Buffer remaining input */ + memcpy(&context->buffer[index], &input[i], inputLen-i); +} + +/* + * MD5 finalization. Ends an MD5 message-digest operation, writing the + * the message digest and zeroizing the context. + */ +void +MD5Final(unsigned char *digest, MD5_CTX *context, int digestlen) +{ + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + Encode(bits, context->count, 8, sizeof(bits)); + + /* Pad out to 56 mod 64. */ + index = (context->count[0] >> 3) & 0x3f; + padLen = (index < 56) ? (56 - index) : (120 - index); + MD5Update(context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update(context, bits, 8); + + /* Store state in digest */ + Encode(digest, context->state, 16, digestlen); + + /* Zeroize sensitive information. */ + memset(context, 0, sizeof(MD5_CTX)); +} + +/* + * MD5 basic transformation. Transforms state based on block. + */ +static void +MD5Transform(uint32_t *state, const unsigned char *block) +{ + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + memset(x, 0, sizeof(x)); +} + +/* + * Encodes input (uint32_t) into output (unsigned char). Assumes len is + * a multiple of 4. + */ +static void +Encode(unsigned char *output, uint32_t *input, unsigned int len, int outputlen) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len && j <= outputlen-4; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } + + if (j > outputlen-4 && j < len) + log_warn("Digest would be too big, truncated."); +} + +/* + * Decodes input (unsigned char) into output (uint32_t). Assumes len is + * a multiple of 4. + */ +static void +Decode(uint32_t *output, const unsigned char *input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) | + (((uint32_t)input[j+2]) << 16) | + (((uint32_t)input[j+3]) << 24); +} diff --git a/server/md5.h b/server/md5.h new file mode 100644 index 0000000..5f48d41 --- /dev/null +++ b/server/md5.h @@ -0,0 +1,48 @@ +/* $Id: md5.h,v 1.2 2000/03/27 22:23:25 shmit Exp $ */ + +/* + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. + * All rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD5 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD5 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +#ifndef MD5_H +# define MD5_H + +#include "compat.h" + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; + +/* MD5 context. */ +typedef struct { + uint32_t state[4]; /* state (ABCD) */ + uint32_t count[2]; /* number of bits, modulo 2^64 */ + /* (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void MD5Init(MD5_CTX *); +void MD5Update(MD5_CTX *, const unsigned char *, unsigned int); +void MD5Final(unsigned char *, MD5_CTX *, int outputlen); +void md5_calc(unsigned char *output, const unsigned char *input, + unsigned int inlen, int outputlen); + +#endif /* MD5_H */ diff --git a/server/memdb.c b/server/memdb.c new file mode 100644 index 0000000..501d0ef --- /dev/null +++ b/server/memdb.c @@ -0,0 +1,501 @@ +#include "conf.h" +#include "config.h" +#include "array.h" +#include "log.h" +#include "md5.h" +#include "memdb.h" +#include "thread.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +RCSID("$Id: memdb.c,v 1.27 2001/10/04 23:57:10 shmit Exp $"); + +#define HASHSIZE 1024 + +extern time_t cdb_mtime; + +enum _cachetype_t { C_DEL, C_UPD, C_TRYVAL, C_EXPIRE }; +typedef enum _cachetype_t cachetype_t; + +struct _mement_t { + char *key; + int keylen; + array_t *vals; + time_t *upd_time; + cachetype_t type; + void *typeval; +}; +typedef struct _mement_t mement_t; + +struct _cachent_t { + mement_t ent; + struct _cachent_t *next; +}; +typedef struct _cachent_t cachent_t; + +struct _counter_t { + float onemin, fivemin, fifteenmin; +}; +typedef struct _counter_t counter_t; + +extern short db_fieldcount; + +static cachent_t **memdb = NULL; +static int memdbsize; +static rw_mutex_t *memdb_lk = NULL; + +static int query_sec, add_sec, del_sec, upd_sec; +static counter_t queryrate; +static counter_t addrate; +static counter_t delrate; +static counter_t updrate; + +static unsigned int +hashkey(const char *key, int keylen) +{ + char md5hash[32]; + unsigned int rc; + + memset(md5hash, 0, sizeof(md5hash)); + md5_calc(md5hash, key, keylen, sizeof(md5hash)); + memcpy(&rc, md5hash, sizeof(rc)); + return (rc % HASHSIZE); +} + +static void +ent_delete(mement_t *ent) +{ + if (ent == NULL) + return; + + if (ent->key != NULL) + free(ent->key); + if (ent->vals != NULL) + array_delete(ent->vals); + if (ent->upd_time != NULL) + free(ent->upd_time); + if (ent->typeval != NULL) + free(ent->typeval); +} + +int +memdb_new() +{ + cachent_t **newdb; + int i; + int rc; + + log_info("Initialising memdb interface."); + + if (memdb_lk == NULL) { + memdb_lk = malloc(sizeof(rw_mutex_t)); + if (memdb_lk == NULL) { + log_err("Couldn't allocate memdb mutex: %s.", + strerror(errno)); + return -1; + } + rc = rw_mutex_new(memdb_lk); + if (rc) { + log_err("Couldn't initialise memdb mutex: %s.", + strerror(rc)); + return -1; + } + } + + newdb = malloc(HASHSIZE * sizeof(cachent_t *)); + if (newdb == NULL) { + log_err("Couldn't allocate new memdb: %s.", strerror(errno)); + return -1; + } + + for (i = 0; i < HASHSIZE; i++) + newdb[i] = NULL; + + rw_mutex_write_lock(memdb_lk); + if (memdb != NULL) + memdb_delete(memdb); + memdb = newdb; + rw_mutex_unlock(memdb_lk); + + query_sec = add_sec = del_sec = upd_sec = 0; + queryrate.onemin = queryrate.fivemin = queryrate.fifteenmin = 0; + addrate.onemin = addrate.fivemin = addrate.fifteenmin = 0; + delrate.onemin = delrate.fivemin = delrate.fifteenmin = 0; + updrate.onemin = updrate.fivemin = updrate.fifteenmin = 0; + memdbsize = 0; + + log_info("memdb interface initialised."); + return 0; +} + +void +memdb_delete() +{ + int i; + + if (memdb == NULL) + return; + + for (i = 0; i < HASHSIZE; i++) { + cachent_t *p; + + p = memdb[i]; + while (p != NULL) { + cachent_t *q; + + q = p->next; + ent_delete(&p->ent); + free(p); + p = q; + } + } + free(memdb); + memdb = NULL; +} + +int +memdb_add(const char *key, int keylen, array_t *vals) +{ + cachent_t *ent; + int hkey; + time_t curtime; + + ent = malloc(sizeof(cachent_t)); + if (ent == NULL) { + log_err("Couldn't create memdb entry for `%s': %s.", + key, strerror(errno)); + return -1; + } + ent->next = NULL; + ent->ent.key = NULL; + ent->ent.type = C_UPD; + ent->ent.typeval = NULL; + ent->ent.upd_time = NULL; + + ent->ent.key = malloc((keylen + 1) * sizeof(char)); + if (ent->ent.key == NULL) { + log_err("Couldn't create entry key for `%s': %s.", + key, strerror(errno)); + ent_delete(&ent->ent); + return -1; + } + memcpy(ent->ent.key, key, keylen); + ent->ent.keylen = keylen; + + ent->ent.vals = array_new(); + if (ent->ent.vals == NULL) { + ent_delete(&ent->ent); + return -1; + } + if (array_dup(ent->ent.vals, vals) == -1) { + ent_delete(&ent->ent); + return -1; + } + + ent->ent.upd_time = malloc(sizeof(time_t)); + if (ent->ent.upd_time == NULL) { + ent_delete(&ent->ent); + return -1; + } + curtime = time(NULL); + memcpy(ent->ent.upd_time, &curtime, sizeof(time_t)); + + /* Cache non-results for a minute. */ + if (vals->nitems == 0) { + time_t expire; + + ent->ent.type = C_EXPIRE; + ent->ent.typeval = malloc(sizeof(time_t)); + expire = time(NULL); + expire += config.null_cache_timeout; + memcpy(ent->ent.typeval, &expire, sizeof(time_t)); + } + + hkey = hashkey(key, keylen); + rw_mutex_write_lock(memdb_lk); + if (memdb[hkey] == NULL) { + memdb[hkey] = ent; + memdbsize++; + } else { + cachent_t *p, *q; + + p = memdb[hkey]; + q = NULL; + while (p->next != NULL && + !(keylen == p->ent.keylen && + memcmp(p->ent.key, key, p->ent.keylen) == 0)) { + q = p; + p = p->next; + } + if (keylen == p->ent.keylen && + memcmp(p->ent.key, key, keylen) == 0) { + /* Already in memdb. */ + + log_info("(add) %s already exists.", key); + + switch (p->ent.type) { + case C_EXPIRE: + case C_DEL: + /* + * Deletable entries. Trash 'em and + * add 'em. + */ + + if (q == NULL) + memdb[hkey] = ent; + else + q->next = ent; + ent->next = p->next; + + ent_delete(&p->ent); + free(p); + break; + default: + /* XXX: Do an update instead of an add. */ + } + } else { + p->next = ent; + memdbsize++; + } + } + + add_sec++; + rw_mutex_unlock(memdb_lk); + return 0; +} + +int +memdb_del(const char *key, int keylen) +{ + cachent_t *p; + int hkey; + + hkey = hashkey(key, keylen); + + rw_mutex_read_lock(memdb_lk); + p = memdb[hkey]; + while (p != NULL && + (keylen != p->ent.keylen || memcmp(p->ent.key, key, keylen))) + p = p->next; + + if (p == NULL) { + array_t *aa; + + /* + * Entry not found. We have to add it ourselves. + */ + rw_mutex_unlock(memdb_lk); + + aa = array_new(); + if (aa == NULL) + return -1; + if (memdb_add(key, keylen, aa) == -1) + return -1; + + /* + * The entry has been added - now go back and mark it + * for deletion. + */ + return memdb_del(key, keylen); + } + + rw_mutex_write_lock(memdb_lk); + if (p->ent.typeval != NULL) { + free(p->ent.typeval); + p->ent.typeval = NULL; + } + + p->ent.type = C_DEL; + if (p->ent.vals != NULL) + array_delete(p->ent.vals); + + del_sec++; + rw_mutex_unlock(memdb_lk); + + return 0; +} + +int +memdb_get(const char *key, int keylen, array_t *vals) +{ + cachent_t *p, *q; + int hkey; + + hkey = hashkey(key, keylen); + rw_mutex_read_lock(memdb_lk); + p = memdb[hkey]; + q = NULL; + while (p != NULL && + (keylen != p->ent.keylen || memcmp(p->ent.key, key, keylen))) { + q = p; + p = p->next; + } + + if (p == NULL) { + rw_mutex_unlock(memdb_lk); + return -1; + } + + switch (p->ent.type) { + case C_DEL: + rw_mutex_unlock(memdb_lk); + query_sec++; + return 0; + case C_EXPIRE: + if (p->ent.typeval != NULL) { + time_t now, expire; + + now = time(NULL); + expire = *((time_t *)p->ent.typeval); + if (now >= expire) { + ent_delete(&p->ent); + if (q != NULL) + q->next = p->next; + else + memdb[hkey] = p->next; + free(p); + rw_mutex_unlock(memdb_lk); + log_info("DEBUG: (get) %s has expired", key); + return -1; + } + } + break; + default: + if (p->ent.upd_time != NULL) { + time_t upd_time; + + upd_time = *p->ent.upd_time; + if (cdb_mtime > upd_time) { + ent_delete(&p->ent); + if (q != NULL) + q->next = p->next; + else + memdb[hkey] = p->next; + free(p); + rw_mutex_unlock(memdb_lk); + log_info("DEBUG: (get) %s is out of date", key); + return -1; + } + } + break; + } + + if (array_dup(vals, p->ent.vals) == -1) { + rw_mutex_unlock(memdb_lk); + return -1; + } + + rw_mutex_unlock(memdb_lk); + query_sec++; + return 0; +} + +int +memdb_upd(const char *key, int keylen, array_t *vals) +{ + cachent_t *p; + int hkey; + time_t curtime; + + /* First make sure that we have enough values. */ + if (vals->nitems != db_fieldcount) { + log_err("Update tried with wrong value count."); + return -1; + } + + hkey = hashkey(key, keylen); + rw_mutex_read_lock(memdb_lk); + p = memdb[hkey]; + while (p != NULL && + (keylen != p->ent.keylen || memcmp(p->ent.key, key, keylen))) + p = p->next; + + if (p == NULL) { + /* Entry not found. Add it ourselves. */ + rw_mutex_unlock(memdb_lk); + return memdb_add(key, keylen, vals); + } + rw_mutex_unlock(memdb_lk); + + /* Entry found, lets replace it with our copy. */ + + rw_mutex_write_lock(memdb_lk); + p->ent.type = C_UPD; + p->ent.typeval = NULL; + curtime = time(NULL); + memcpy(p->ent.upd_time, &curtime, sizeof(time_t)); + array_delete(p->ent.vals); + + p->ent.vals = array_new(); + if (p->ent.vals == NULL) { + rw_mutex_unlock(memdb_lk); + return -1; + } + + if (array_dup(p->ent.vals, vals) == -1) { + rw_mutex_unlock(memdb_lk); + return -1; + } + + upd_sec++; + rw_mutex_unlock(memdb_lk); + + return 0; +} + +int +memdb_stats(array_t *statarr) +{ + char buffer[512]; + + /* Convert q/m, q/5m, and q/15m into q/s. */ + snprintf(buffer, sizeof(buffer), "MEMDB get: %.2f, %.2f, %.2f", + queryrate.onemin, queryrate.fivemin, queryrate.fifteenmin); + if (array_add(statarr, strlen(buffer), buffer, ARRTERM) == -1) + return -1; + + snprintf(buffer, sizeof(buffer), "MEMDB add: %.2f, %.2f, %.2f", + addrate.onemin, addrate.fivemin, addrate.fifteenmin); + if (array_add(statarr, strlen(buffer), buffer, ARRTERM) == -1) + return -1; + + snprintf(buffer, sizeof(buffer), "MEMDB del: %.2f, %.2f, %.2f", + delrate.onemin, delrate.fivemin, delrate.fifteenmin); + if (array_add(statarr, strlen(buffer), buffer, ARRTERM) == -1) + return -1; + + snprintf(buffer, sizeof(buffer), "MEMDB upd: %.2f, %.2f, %.2f", + updrate.onemin, updrate.fivemin, updrate.fifteenmin); + if (array_add(statarr, strlen(buffer), buffer, ARRTERM) == -1) + return -1; + + snprintf(buffer, sizeof(buffer), "MEMDB total entries: %d", memdbsize); + return array_add(statarr, strlen(buffer), buffer, ARRTERM); +} + +void +memdb_collate() +{ + queryrate.onemin = ((queryrate.onemin * 59) + query_sec) / 60; + queryrate.fivemin = ((queryrate.fivemin * 299) + query_sec) / 300; + queryrate.fifteenmin = ((queryrate.fifteenmin * 899) + query_sec) / 900; + query_sec = 0; + + addrate.onemin = ((addrate.onemin * 59) + add_sec) / 60; + addrate.fivemin = ((addrate.fivemin * 299) + add_sec) / 300; + addrate.fifteenmin = ((addrate.fifteenmin * 899) + add_sec) / 900; + add_sec = 0; + + delrate.onemin = ((delrate.onemin * 59) + del_sec) / 60; + delrate.fivemin = ((delrate.fivemin * 299) + del_sec) / 300; + delrate.fifteenmin = ((delrate.fifteenmin * 899) + del_sec) / 900; + del_sec = 0; + + updrate.onemin = ((updrate.onemin * 59) + upd_sec) / 60; + updrate.fivemin = ((updrate.fivemin * 299) + upd_sec) / 300; + updrate.fifteenmin = ((updrate.fifteenmin * 899) + upd_sec) / 900; + upd_sec = 0; +} diff --git a/server/memdb.h b/server/memdb.h new file mode 100644 index 0000000..0822e61 --- /dev/null +++ b/server/memdb.h @@ -0,0 +1,17 @@ +/* $Id: memdb.h,v 1.8 2000/05/17 19:32:58 shmit Exp $ */ + +#ifndef MEMDB_H +#define MEMDB_H + +int memdb_new(); +void memdb_delete(); + +int memdb_add(const char *key, int keylen, array_t *vals); +int memdb_del(const char *key, int keylen); +int memdb_get(const char *key, int keylen, array_t *vals); +int memdb_upd(const char *key, int keylen, array_t *vals); + +int memdb_stats(array_t *statarr); +void memdb_collate(); + +#endif diff --git a/server/mysqldb.c b/server/mysqldb.c new file mode 100644 index 0000000..517c15b --- /dev/null +++ b/server/mysqldb.c @@ -0,0 +1,163 @@ +#include "conf.h" +#include "array.h" +#include "config.h" +#include "nastdio.h" +#include "log.h" +#include "mysqldb.h" +#include "thread.h" + +#include <errno.h> +#include <errmsg.h> +#include <mysql.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +RCSID("$Id: mysqldb.c,v 1.30 2001/10/10 20:29:47 shmit Exp $"); + +extern fieldent *db_fields; +extern char db_key[1024]; +extern char db_dbn[1024]; +extern char db_tbl[1024]; +extern short db_fieldcount; + +static char cols[512]; + +static int sec_c; +static float onemin_c, fivemin_c, fifteenmin_c; + +int +mysqldb_new() +{ + int i; + + sec_c = 0; + onemin_c = fivemin_c = fifteenmin_c = 0; + + cols[0] = '\0'; + for (i = 0; i < db_fieldcount; i++) { + strncat(cols, db_fields[i].name, sizeof(cols)); + if (i < db_fieldcount-1) + strncat(cols, ",", sizeof(cols)); + } + + return 0; +} + +void * +mysqldb_connect_new() +{ + MYSQL *dbh; + + log_info("Initialising MySQL database."); + + dbh = mysql_init(NULL); + if (dbh == NULL) { + log_err("Couldn't allocate mysql handle: %s.", + strerror(errno)); + return NULL; + } + + if (!mysql_connect(dbh, config.mysql_host, + config.mysql_user, config.mysql_pass)) { + log_err("Couldn't open connection to database: %s.", + mysql_error(dbh)); + mysqldb_connect_close(dbh); + return NULL; + } + + if (mysql_select_db(dbh, db_dbn)) { + log_err("Couldn't open database: %s.", + mysql_error(dbh)); + mysqldb_connect_close(dbh); + return NULL; + } + + log_info("MySQL database interface initialised."); + return (void *)dbh; +} + +void +mysqldb_connect_close(void *dbh) +{ + if (dbh != NULL) { + log_info("MySQL connection shutting down."); + mysql_close(dbh); + free(dbh); + } +} + +int +mysqldb_get(reqthread_t *self, const char *key, int keylen, array_t *aa) +{ + MYSQL *dbh; + MYSQL_RES *result; + char buffer[1024]; + MYSQL_ROW row; + int i, rc; + + snprintf(buffer, sizeof(buffer), DBSELECT, cols, db_tbl, db_key, key); + + if (self->arg == NULL) { + self->arg = mysqldb_connect_new(); + if (self->arg == NULL) + return -1; + } + dbh = (MYSQL *)self->arg; + + rc = mysql_query(dbh, buffer); + if (rc) { + log_err("Error performing query: %s.", mysql_error(dbh)); + mysqldb_connect_close(dbh); + self->arg = NULL; + return -1; + } + + result = mysql_use_result(dbh); + row = mysql_fetch_row(result); + if (row == NULL) { + log_info("Couldn't find %s in MySQL database.", + key); + mysql_free_result(result); + sec_c++; + return 1; + } + + if (mysql_num_fields(result) < db_fieldcount) { + log_err("MySQL server didn't return all fields."); + mysql_free_result(result); + return 0; + } + + for (i = 0; i < db_fieldcount; i++) { + if (array_add(aa, strlen(row[i]), row[i], ARRTERM) == -1) { + mysql_free_result(result); + return -1; + } + } + while (mysql_fetch_row(result)); + mysql_free_result(result); + + sec_c++; + + return 0; +} + +int +mysqldb_stats(array_t *statarr) +{ + char buffer[512]; + + snprintf(buffer, sizeof(buffer), "MySQL: %.2f, %.2f, %.2f", + onemin_c, fivemin_c, fifteenmin_c); + return array_add(statarr, strlen(buffer), buffer, ARRTERM); +} + +void +mysqldb_collate() +{ + onemin_c = ((onemin_c * 59) + sec_c) / 60; + fivemin_c = ((fivemin_c * 299) + sec_c) / 300; + fifteenmin_c = ((fifteenmin_c * 899) + sec_c) / 900; + sec_c = 0; +} diff --git a/server/mysqldb.h b/server/mysqldb.h new file mode 100644 index 0000000..c5c703c --- /dev/null +++ b/server/mysqldb.h @@ -0,0 +1,17 @@ +/* $Id: mysqldb.h,v 1.7 2000/11/08 20:04:55 shmit Exp $ */ + +#ifndef MYSQLDB_H +#define MYSQLDB_H + +#include "array.h" +#include "fqm.h" + +int mysqldb_new(); +void *mysqldb_connect_new(); +void mysqldb_connect_close(void *dbh); +int mysqldb_get(reqthread_t *self, const char *key, int keylen, array_t *aa); + +int mysqldb_stats(array_t *statarr); +void mysqldb_collate(); + +#endif diff --git a/server/nastd.c b/server/nastd.c new file mode 100644 index 0000000..3c015a6 --- /dev/null +++ b/server/nastd.c @@ -0,0 +1,224 @@ +#include "conf.h" +#include "config.h" +#include "nastdio.h" +#include "nastipc.h" +#include "cdb.h" +#include "fqm.h" +#include "log.h" +#include "memdb.h" +#include "mysqldb.h" +#include "periodic.h" + +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <time.h> +#include <unistd.h> + +RCSID("$Id: nastd.c,v 1.8 2001/11/09 15:54:38 shmit Exp $"); + +char *progname; +time_t start_time; + +static int +make_u_csock() +{ + struct sockaddr_un sunix; + int sock; + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock == -1) { + log_err("Couldn't create unix socket: %s.", strerror(errno)); + return -1; + } + + memset(&sunix, 0, sizeof(sunix)); + snprintf(sunix.sun_path, sizeof(sunix.sun_path), config.nast_sock); + sunix.sun_family = AF_UNIX; + (void)unlink(sunix.sun_path); + + if (bind(sock, (struct sockaddr *)&sunix, sizeof(sunix)) == -1) { + log_err("Couldn't bind to unix socket: %s.", strerror(errno)); + return -1; + } + (void)listen(sock, 10); + + return sock; +} + +static int +make_i_csock() +{ + struct sockaddr_in sinet; + int sock; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) { + log_err("Couldn't create inet socket: %S.", strerror(errno)); + return -1; + } + + memset(&sinet, 0, sizeof(sinet)); + sinet.sin_family = AF_INET; + sinet.sin_addr.s_addr = INADDR_ANY; + sinet.sin_port = htons(config.tcp_port); + if (bind(sock, (struct sockaddr *)&sinet, sizeof(sinet)) == -1) { + log_err("Couldn't bind to inet socket: %s.", strerror(errno)); + return -1; + } + (void)listen(sock, 10); + + return sock; +} + +static int +do_client_connect(int sock) +{ + struct sockaddr_un saremote; + int addrlen; + int s; + + addrlen = sizeof(saremote); + s = accept(sock, (struct sockaddr *)&saremote, &addrlen); + if (s == -1) { + log_err("Couldn't accept new connection: %s.", + strerror(errno)); + return -1; + } + io_new(s); + + return 0; +} + +static int +init_daemon() +{ + sigset_t sigmask; + + log_open(); + if (cdb_new()) + return -1; + mysqldb_new(); + if (memdb_new()) + return -1; + + /* + * Turn off SIGPIPE. The calls to write() will return fine with + * it off, and this means we don't have to do any signal mojo. + */ + (void)sigemptyset(&sigmask); + (void)sigaddset(&sigmask, SIGPIPE); + (void)sigprocmask(SIG_BLOCK, &sigmask, NULL); + + /* Now we daemonise. */ + switch (fork()) { + case 0: + setsid(); + close(STDIN_FILENO); + close(STDOUT_FILENO); + break; + case -1: + log_err("Couldn't fork into daemon: %s.", strerror(errno)); + return -1; + default: + exit(0); + } + + return 0; +} + +void +usage() +{ + fprintf(stderr, "Usage: %s [options]\n" + "\t-d directory\tSpecify directory for nast files.\n", + progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char ch; + int u_csock, i_csock; + + progname = strrchr(argv[0], '/'); + if (!progname) + progname = argv[0]; + else + progname++; + + /* Initialise configuration values from file. */ + config_setdefaults(); + while ((ch = getopt(argc, argv, "d:")) != -1) { + switch (ch) { + case 'd': + config.nast_dir = optarg; + break; + default: + usage(); + /* NOTREACHED */ + } + } + if (config_init()) + return 1; + + if (init_daemon()) { + log_err("Couldn't initialise nastd. Exiting."); + return 1; + } + + u_csock = make_u_csock(); + if (u_csock == -1) + return 1; + + i_csock = make_i_csock(); + if (i_csock == -1) + return 1; + + /* Create the FQM threads. */ + (void)fqm_new(10); + + /* + * Creat a thread that runs periodically. + */ + if (periodic_new() == -1) { + log_err("Couldn't start periodic thread. Exiting."); + return 1; + } + + start_time = time(NULL); + + /* + * Main control loop. Sit on the socket and wait for a client to + * connect. As soon as it does, make another thread to handle it. + */ + for (;;) { + fd_set read_fds; + int rc; + + FD_ZERO(&read_fds); + FD_SET(i_csock, &read_fds); + FD_SET(u_csock, &read_fds); + + rc = select(10, &read_fds, NULL, NULL, NULL); + if (rc == -1) { + log_err("Couldn't select on sockets: %s.", + strerror(errno)); + sleep(30); + } + + if (FD_ISSET(i_csock, &read_fds)) + (void)do_client_connect(i_csock); + + if (FD_ISSET(u_csock, &read_fds)) + (void)do_client_connect(u_csock); + } + return 0; +} diff --git a/server/nastdio.c b/server/nastdio.c new file mode 100644 index 0000000..dd7ccd3 --- /dev/null +++ b/server/nastdio.c @@ -0,0 +1,701 @@ +#include "conf.h" +#include "array.h" +#include "nastd.h" +#include "nastdio.h" +#include "nastipc.h" +#include "cdb.h" +#include "fqm.h" +#include "log.h" +#include "memdb.h" +#include "mysqldb.h" +#include "thread.h" + +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> + +RCSID("$Id: nastdio.c,v 1.13 2001/10/29 11:17:13 shmit Exp $"); + +extern fqm_t *fqm; + +extern fieldent *db_fields; +extern char db_key[1024]; +extern short db_fieldcount; + +extern time_t start_time; + +struct _client_opts { + nast_options *opts; + rw_mutex_t *opt_lk; + thread_t *tid; + int sock; +}; +typedef struct _client_opts client_opts; + +static int +arr_send_response(int sock, short reqid, char r_code, array_t *aa) +{ + char *s; + char buffer[1024]; + short l, i; + ssize_t wrote; + + /* Save space for buffer length. */ + l = sizeof(short); + + /* Add request ID. */ + memcpy(buffer+l, &htons(reqid), sizeof(reqid)); + l += sizeof(reqid); + + /* Add OK or ERR. */ + buffer[l] = r_code; + l += sizeof(char); + + /* + * Build the string to be sent back to the client. + */ + for (i = 0; i < aa->nitems; i++) { + int slen; + + s = aa->items[i]->str; + slen = aa->items[i]->strlen; + if (l+slen > sizeof(buffer)) { + log_err("Buffer isn't big enough for all data."); + return -1; + } + memcpy(buffer+l, s, slen); + l += slen; + + if (i < aa->nitems-1) { + buffer[l] = NASTSEP; + l++; + } + } + + /* Fill in buffer length. */ + memcpy(buffer, &htons(l), sizeof(short)); + + wrote = 0; + while (wrote < l) { + ssize_t rc; + + rc = write(sock, buffer + wrote, l - wrote); + if (rc == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + log_err("Couldn't write response: %s.", + strerror(errno)); + return -1; + } + wrote += rc; + } + + return 0; +} + +static int +send_response(int sock, short reqid, char r_code, ...) +{ + array_t *aa; + int rc; + va_list ap; + + aa = array_new(); + va_start(ap, r_code); + if (va_array_add(aa, ap) == -1) { + va_end(ap); + array_delete(aa); + return -1; + } + va_end(ap); + + rc = arr_send_response(sock, reqid, r_code, aa); + array_delete(aa); + return rc; +} + +static int +do_opt_set(int s, short reqid, client_opts *cops, const char *buffer, + size_t bufflen) +{ + int i; + + rw_mutex_write_lock(cops->opt_lk); + for (i = 0; i < bufflen; i += 2) { + switch (buffer[i]) { + case OPTQCACHE: + if (buffer[i+1] == OPTFALSE) + cops->opts->use_qcache = NASTFALSE; + else + cops->opts->use_qcache = NASTTRUE; + break; + case OPTLOCALDB: + if (buffer[i+1] == OPTFALSE) + cops->opts->use_localdb = NASTFALSE; + else + cops->opts->use_localdb = NASTTRUE; + break; + case OPTFALLASYNC: + if (buffer[i+1] == OPTFALSE) + cops->opts->fallthrough_async = NASTFALSE; + else + cops->opts->fallthrough_async = NASTTRUE; + break; + case OPTALWAYSFALL: + if (buffer[i+1] == OPTFALSE) + cops->opts->always_fallthrough = NASTFALSE; + else + cops->opts->always_fallthrough = NASTTRUE; + break; + case OPTFAILONCE: + if (buffer[i+1] == OPTFALSE) + cops->opts->fail_once = NASTFALSE; + else + cops->opts->fail_once = NASTTRUE; + break; + case OPTNOFALLTHROUGH: + if (buffer[i+1] == OPTFALSE) + cops->opts->no_fallthrough = NASTFALSE; + else + cops->opts->no_fallthrough = NASTTRUE; + break; + default: + rw_mutex_unlock(cops->opt_lk); + log_err("Unknown option: `0x%x'.\n", buffer[i]); + (void)send_response(s, reqid, NASTERR, + strlen("Sent unknown option"), + "Sent unknown option", ARRTERM); + return -1; + } + } + rw_mutex_unlock(cops->opt_lk); + + if (send_response(s, reqid, NASTOK, ARRTERM) == -1) + return -1; + return 0; +} + +static int +do_opt_get(int s, short reqid, client_opts *cops) +{ + char buffer[512]; + int bufflen; + + bufflen = 0; + rw_mutex_read_lock(cops->opt_lk); + + buffer[bufflen] = OPTQCACHE; + if (cops->opts->use_qcache) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTLOCALDB; + if (cops->opts->use_localdb) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTFALLASYNC; + if (cops->opts->fallthrough_async) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTALWAYSFALL; + if (cops->opts->always_fallthrough) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTFAILONCE; + if (cops->opts->fail_once) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = OPTNOFALLTHROUGH; + if (cops->opts->no_fallthrough) + buffer[bufflen+1] = OPTTRUE; + else + buffer[bufflen+1] = OPTFALSE; + bufflen += 2; + + buffer[bufflen] = '\0'; + + rw_mutex_unlock(cops->opt_lk); + + if (send_response(s, reqid, NASTOK, bufflen, buffer, ARRTERM) == -1) + return -1; + return 0; +} + +static +REQHANDLER(do_fallthrough) +{ + array_t *aa; + int rc; + + aa = array_new(); + if (aa == NULL) { + log_info("Couldn't allocate array: %s.", strerror(errno)); + (void)send_response(req->sock, req->reqid, NASTERR, + strlen("Couldn't allocate return buffer"), + "Couldn't allocate return buffer", ARRTERM); + return -1; + } + + rc = mysqldb_get(self, req->req, strlen(req->req), aa); + if (rc == -1) { + log_info("Couldn't find %s in MySQL DB.", req->req); + rc = send_response(req->sock, req->reqid, NASTOK, ARRTERM); + array_delete(aa); + return -1; + } + + if (arr_send_response(req->sock, req->reqid, NASTOK, aa) == -1) { + array_delete(aa); + return -1; + } + + /* If we're this far, the memdb doesn't have this key. Add it. */ + (void)memdb_add(req->req, strlen(req->req), aa); + + array_delete(aa); + + return 0; +} + +static int +do_get(int s, short reqid, client_opts *cops, const char *buffer, + size_t bufflen) +{ + int fallthrough_flag; + array_t *aa; + + aa = array_new(); + if (aa == NULL) { + log_info("Couldn't allocate array: %s.", strerror(errno)); + (void)send_response(s, reqid, NASTERR, + strlen("Couldn't allocate return buffer"), + "Couldn't allocate return buffer", ARRTERM); + return -1; + } + + /* Check memdb first. */ + if (cops->opts->use_qcache && !cops->opts->always_fallthrough) { + if (memdb_get(buffer, bufflen, aa) == 0) { + log_info("Found `%s' in memdb.", buffer); + if (arr_send_response(s, reqid, NASTOK, aa) == -1) { + array_delete(aa); + return -1; + } + array_delete(aa); + return 0; + } + } + + /* Just do a CDB lookup for now. */ + if (!cops->opts->always_fallthrough && cops->opts->use_localdb) { + fallthrough_flag = cdb_get(buffer, bufflen, aa); + if (fallthrough_flag == -1) + log_info("Couldn't find `%s' in CDB file.", buffer); + } else { + fallthrough_flag = -1; + } + + /* + * If fallthrough_flag is -1, then the CDB query failed, so + * we should check fallthrough. + */ + if (fallthrough_flag == -1 && !cops->opts->no_fallthrough) { + request_t *req; + + array_delete(aa); + + log_info("Checking fallthrough for `%s'.", buffer); + req = req_new(s, reqid, do_fallthrough, + buffer, bufflen); + if (req == NULL) { + log_err("Couldn't build request for FQM."); + send_response(s, reqid, NASTERR, + strlen("Couldn't build FQM req"), + "Couldn't build FQM req", ARRTERM); + return -1; + } + + if (fqm_push(fqm, req) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't add req to FQM"), + "Couldn't add req to FQM", ARRTERM); + req_delete(req); + return -1; + } + return 0; + } + + if (arr_send_response(s, reqid, NASTOK, aa) == -1) { + array_delete(aa); + return -1; + } + array_delete(aa); + + return 0; +} + +static array_t * +build_array(const char *buff, size_t bufflen) +{ + array_t *aa; + const char *ep, *sp; + + aa = array_new(); + if (aa == NULL) { + log_err("Couldn't allocate array for input buffer."); + return NULL; + } + + sp = buff; + for (ep = sp; ep <= buff+bufflen; ep++) { + if ((ep == buff+bufflen || *ep == NASTSEP) && + ep - sp > 0) { + if (array_add(aa, ep-sp, sp, ARRTERM) == -1) { + log_err("Couldn't add item to input array."); + array_delete(aa); + return NULL; + } + sp = ep+1; + } + } + + return aa; +} + +static int +do_update(int s, short reqid, client_opts *cops, const char *buffer, + size_t bufflen) +{ + array_t *aa; + char *key; + int keylen; + + for (keylen = 0; keylen < bufflen; keylen++) { + if (buffer[keylen] == NASTSEP) + break; + } + + if (keylen == bufflen) { + /* Request only contains key. That's bad. */ + return send_response(s, reqid, NASTERR, + strlen("Need values for update"), + "Need values for update", ARRTERM); + } + + key = malloc(sizeof(char) * keylen + 1); + if (key == NULL) { + log_err("Couldn't allocate key for update: %s.", + strerror(errno)); + send_response(s, reqid, NASTERR, + strlen("Couldn't allocate key"), + "Couldn't allocate key", ARRTERM); + return -1; + } + memcpy(key, buffer, keylen); + key[keylen + 1] = '\0'; + + aa = build_array(buffer+keylen + 1, bufflen-keylen - 1); + if (aa == NULL) { + send_response(s, reqid, NASTERR, + strlen("Couldn't build your input array"), + "Couldn't build your input array", ARRTERM); + return -1; + } + + if (memdb_upd(key, keylen, aa) == -1) { + array_delete(aa); + return send_response(s, reqid, NASTERR, + strlen("Couldn't update cache"), + "Couldn't update cache", ARRTERM); + } + array_delete(aa); + + return send_response(s, reqid, NASTOK, ARRTERM); +} + +static int +do_stats(int s, int reqid) +{ + array_t *aa; + char buffer[512]; + int up_day, up_hour, up_min, up_sec; + time_t uptime; + + aa = array_new(); + + /* Gather stats from the various databases. */ + if (mysqldb_stats(aa) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't get stats from MySQL"), + "Couldn't get stats from MySQL", ARRTERM); + array_delete(aa); + return -1; + } + + if (cdb_stats(aa) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't get stats from cdb"), + "Couldn't get stats from cdb", ARRTERM); + array_delete(aa); + return -1; + } + + if (memdb_stats(aa) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't get stats from memdb"), + "Couldn't get stats from memdb", ARRTERM); + array_delete(aa); + return -1; + } + + uptime = time(NULL) - start_time; + up_day = uptime / 86400; uptime -= up_day * 86400; + up_hour = uptime / 3600; uptime -= up_hour * 3600; + up_min = uptime / 60; uptime -= up_min * 60; + up_sec = uptime; + + snprintf(buffer, sizeof(buffer), + "Uptime: %d day(s), %02d:%02d:%02d", + up_day, up_hour, up_min, up_sec); + if (array_add(aa, strlen(buffer), buffer, ARRTERM) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't return uptime"), + "Couldn't return uptime", ARRTERM); + array_delete(aa); + return -1; + } + + snprintf(buffer, sizeof(buffer), + "Version: %s", VERSION); + if (array_add(aa, strlen(buffer), buffer, ARRTERM) == -1) { + send_response(s, reqid, NASTERR, + strlen("Couldn't return version"), + "Couldn't return version", ARRTERM); + array_delete(aa); + return -1; + } + + /* Now send 'em off. */ + if (arr_send_response(s, reqid, NASTOK, aa) == -1) { + array_delete(aa); + return -1; + } + array_delete(aa); + return 0; +} + +static int +process_cmd(int s, client_opts *cops, const char *buffer, size_t bufflen) +{ + const char *p; + int l; + short len, reqid; + + /* + * bufflen must be at least six bytes or we have a screwed up + * command. + */ + if (bufflen < sizeof(len) + sizeof(reqid) + 2*sizeof(char)) { + log_err("Command sent is too short."); + return -1; + } + + for (p = buffer; p < buffer+bufflen; p += len) { + /* All requests start with a length. */ + memcpy(&len, p, sizeof(reqid)); + len = ntohs(len); + l = sizeof(len); + + /* Follow with a request ID. */ + memcpy(&reqid, p+l, sizeof(reqid)); + reqid = ntohs(reqid); + l += sizeof(reqid); + + /* Then have NASTCMD. Make sure it's there. */ + if (p[l] != NASTCMD) { + log_err("Command doesn't start with NASTCMD."); + return -1; + } + l += sizeof(char); + + /* The next byte says what kind of command it is. */ + switch (p[l++]) { + case NASTDIE: + return 1; + break; + case NASTOPTSET: + if (do_opt_set(s, reqid, cops, p+l, len-l) == -1) + return -1; + break; + case NASTOPTGET: + if (do_opt_get(s, reqid, cops) == -1) + return -1; + break; + case NASTGET: + if (do_get(s, reqid, cops, p+l, len-l) == -1) + return -1; + break; + case NASTADD: + log_err("Add command not supported yet."); + break; + case NASTDEL: + log_err("Delete command not supported yet."); + break; + case NASTUPD: + if (do_update(s, reqid, cops, p+l, len-l) == -1) + return -1; + break; + case NASTSTATS: + if (do_stats(s, reqid) == -1) + return -1; + break; + default: + return -1; + } + } + + return 0; +} + +static void +free_cops(client_opts *cops) +{ + if (cops == NULL) + return; + + close(cops->sock); + if (cops->opts != NULL) + free(cops->opts); + if (cops->opt_lk != NULL) + free(cops->opt_lk); + if (cops->tid != NULL) + free(cops->tid); + free(cops); +} + +static void * +io_looper(void *arg) +{ + client_opts *cops; + + (void)pthread_detach(pthread_self()); + cops = (client_opts *)arg; + + for (;;) { + ssize_t nbytes; + char buffer[1024]; + + nbytes = recv(cops->sock, buffer, sizeof(buffer), 0); + if (nbytes == -1) { + log_err("Couldn't read from socket: %s.", + strerror(errno)); + break; + } + if (nbytes == 0) { + /* Connection has been closed. Terminate. */ + log_info("Connection closed."); + break; + } + buffer[nbytes] = '\0'; + + /* Do command processing on the buffer. */ + if (process_cmd(cops->sock, cops, buffer, nbytes) == 1) + break; + } + + free_cops(cops); + return NULL; +} + +static void +set_default_opts(nast_options *opts) +{ + opts->use_qcache = NASTTRUE; + opts->use_localdb = NASTTRUE; + opts->fallthrough_async = NASTFALSE; + opts->always_fallthrough = NASTFALSE; + opts->fail_once = NASTFALSE; + opts->no_fallthrough = NASTFALSE; +} + +int +io_new(int s) +{ + client_opts *cops; + + log_info("Connection opened."); + + cops = malloc(sizeof(client_opts)); + if (cops == NULL) { + log_err("Couldn't allocate client option structure: %s.", + strerror(errno)); + return -1; + } + + /* Pre-set these. free_cops() relies on them being set. */ + cops->opts = NULL; + cops->opt_lk = NULL; + cops->sock = s; + cops->tid = NULL; + + cops->opts = malloc(sizeof(nast_options)); + if (cops->opts == NULL) { + log_err("Couldn't allocate client options structure: %s.", + strerror(errno)); + free_cops(cops); + return -1; + } + set_default_opts(cops->opts); + + cops->opt_lk = malloc(sizeof(rw_mutex_t)); + if (cops->opt_lk == NULL) { + log_err("Couldn't allocate client options mutex: %s.", + strerror(errno)); + free_cops(cops); + return -1; + } + + if (rw_mutex_new(cops->opt_lk)) { + log_err("Couldn't initialise client options mutex: %s.", + strerror(errno)); + free_cops(cops); + return -1; + } + + cops->tid = malloc(sizeof(thread_t)); + if (cops->tid == NULL) { + log_err("Couldn't allocate initial client thread: %s.", + strerror(errno)); + free_cops(cops); + return -1; + } + + if (thread_new(cops->tid, io_looper, cops)) { + log_err("Couldn't start initial looper thread: %s.", + strerror(errno)); + free_cops(cops); + return -1; + } + + return 0; +} diff --git a/server/nastdio.h b/server/nastdio.h new file mode 100644 index 0000000..e3375f6 --- /dev/null +++ b/server/nastdio.h @@ -0,0 +1,14 @@ +/* $Id: nastdio.h,v 1.1 2000/09/13 20:21:34 shmit Exp $ */ + +#ifndef NASTDIO_H +#define NASTDIO_H + +struct _fieldent { + char *name; + short index; +}; +typedef struct _fieldent fieldent; + +int io_new(int sock); + +#endif diff --git a/server/periodic.c b/server/periodic.c new file mode 100644 index 0000000..9a94edb --- /dev/null +++ b/server/periodic.c @@ -0,0 +1,118 @@ +#include "conf.h" +#include "cdb.h" +#include "log.h" +#include "memdb.h" +#include "mysqldb.h" +#include "thread.h" +#include "periodic.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +RCSID("$Id: periodic.c,v 1.9 2000/05/17 21:52:34 shmit Exp $"); + +struct _per_thread_t { + cond_t *cond; + thread_t *tid; +}; +typedef struct _per_thread_t per_thread_t; + +static void * +periodic_looper(void *arg) +{ + per_thread_t *self; + int count; + + self = (per_thread_t *)arg; + pthread_detach(pthread_self()); + + count = 0; + for (;;) { + struct timespec ts; + + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 1; + (void)cond_timedwait(self->cond, &ts); + + count++; + if (count == PERIODICITY) { + cdb_periodic(); + count = 0; + } + + cdb_collate(); + mysqldb_collate(); + memdb_collate(); + } + return NULL; +} + +void +periodic_delete(per_thread_t *thr) +{ + if (thr == NULL) + return; + + if (thr->cond) { + cond_destroy(thr->cond); + free(thr->cond); + thr->cond = NULL; + } + + if (thr->tid) { + free(thr->tid); + thr->tid = NULL; + } + free(thr); +} + +int +periodic_new() +{ + per_thread_t *per_thread; + int rc; + + per_thread = malloc(sizeof(per_thread_t)); + if (per_thread == NULL) { + log_err("Couldn't allocate periodic thread: %s.", + strerror(errno)); + return -1; + } + per_thread->cond = NULL; + per_thread->tid = NULL; + + per_thread->cond = malloc(sizeof(cond_t)); + if (per_thread->cond == NULL) { + log_err("Couldn't allocate periodic condition: %s.", + strerror(errno)); + periodic_delete(per_thread); + return -1; + } + + rc = cond_new(per_thread->cond); + if (rc) { + log_err("Couldn't initialise periodic condition: %s.", + strerror(rc)); + periodic_delete(per_thread); + return -1; + } + + per_thread->tid = malloc(sizeof(thread_t)); + if (per_thread->tid == NULL) { + log_err("Couldn't allocate periodic thread: %s.", + strerror(rc)); + periodic_delete(per_thread); + return -1; + } + + rc = thread_new(per_thread->tid, periodic_looper, per_thread); + if (rc) { + log_err("Couldn't start periodic thread: %s.", + strerror(rc)); + periodic_delete(per_thread); + return -1; + } + + return 0; +} diff --git a/server/periodic.h b/server/periodic.h new file mode 100644 index 0000000..835fd4a --- /dev/null +++ b/server/periodic.h @@ -0,0 +1,8 @@ +/* $Id: periodic.h,v 1.2 2000/09/13 20:21:35 shmit Exp $ */ + +#ifndef NAST_PERIODIC_H +#define NAST_PERIODIC_H + +int periodic_new(); + +#endif diff --git a/server/thread.c b/server/thread.c new file mode 100644 index 0000000..95737d6 --- /dev/null +++ b/server/thread.c @@ -0,0 +1,216 @@ +#include "conf.h" +#include "log.h" +#include "thread.h" + +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <sys/types.h> +#include <time.h> +#include <unistd.h> + +RCSID("$Id: thread.c,v 1.6 2000/03/21 19:18:24 shmit Exp $"); + +int +thread_new(thread_t *thread, void *(*thread_func)(void *), void *arg) +{ + int rc; + + thread->thread_func = thread_func; + rc = pthread_create(&thread->id, NULL, thread_func, arg); + if (rc != 0) { + log_err("Couldn't create thread: %s.\n", strerror(rc)); + return -1; + } + return 0; +} + +void +thread_kill(thread_t *thread) +{ +} + +int +thread_reload(thread_t *thread) +{ + return 0; +} + +int +mutex_new(mutex_t *lock) +{ + return pthread_mutex_init(lock, NULL); +} + +int +mutex_delete(mutex_t *lock) +{ + return pthread_mutex_destroy(lock); +} + +int +mutex_lock(mutex_t *lock) +{ + return pthread_mutex_lock(lock); +} + +int +mutex_unlock(mutex_t *lock) +{ + return pthread_mutex_unlock(lock); +} + +int +rw_mutex_new(rw_mutex_t *lock) +{ + int rc; + + rc = mutex_new(&lock->lock); + if (rc) + return rc; + rc = pthread_cond_init(&lock->read_sig, NULL); + if (rc) { + mutex_delete(&lock->lock); + return rc; + } + rc = pthread_cond_init(&lock->write_sig, NULL); + if (rc) { + mutex_delete(&lock->lock); + pthread_cond_destroy(&lock->read_sig); + return rc; + } + lock->state = 0; + lock->blocked_writers = 0; + + return 0; +} + +int +rw_mutex_read_lock(rw_mutex_t *lock) +{ + int rc; + + if (lock == NULL) + return EINVAL; + + rc = mutex_lock(&lock->lock); + if (rc) + return rc; + + /* Make sure the writers go before the readers. */ + while (lock->blocked_writers || lock->state < 0) { + rc = pthread_cond_wait(&lock->read_sig, &lock->lock); + if (rc) { + mutex_unlock(&lock->lock); + return rc; + } + } + lock->state++; + mutex_unlock(&lock->lock); + + return rc; +} + +int +rw_mutex_write_lock(rw_mutex_t *lock) +{ + int rc; + + if (lock == NULL) + return EINVAL; + + rc = mutex_lock(&lock->lock); + if (rc) + return rc; + + /* Wait for no readers on the lock. */ + while (lock->state != 0) { + lock->blocked_writers++; + rc = pthread_cond_wait(&lock->write_sig, &lock->lock); + lock->blocked_writers--; + if (rc) { + mutex_unlock(&lock->lock); + return rc; + } + } + lock->state = -1; + + mutex_unlock(&lock->lock); + return rc; +} + +int +rw_mutex_unlock(rw_mutex_t *lock) +{ + int rc; + + if (lock == NULL) + return EINVAL; + + rc = mutex_lock(&lock->lock); + if (rc) + return rc; + + if (lock->state > 0) { + /* We have an open read lock. */ + if (--lock->state == 0 && lock->blocked_writers) + rc = pthread_cond_signal(&lock->write_sig); + } else if (lock->state < 0) { + /* We have an open writer lock. */ + lock->state = 0; + if (lock->blocked_writers) + rc = pthread_cond_signal(&lock->write_sig); + else + rc = pthread_cond_broadcast(&lock->read_sig); + } else + rc = EINVAL; + + mutex_unlock(&lock->lock); + return rc; +} + +int +cond_new(cond_t *cond) +{ + int rc; + + if (cond == NULL) + return EINVAL; + + rc = pthread_cond_init(&cond->id, NULL); + if (rc) + return rc; + + rc = mutex_new(&cond->lock); + if (rc) + pthread_cond_destroy(&cond->id); + + return rc; +} + +int +cond_signal(cond_t *cond) +{ + return pthread_cond_signal(&cond->id); +} + +int +cond_wait(cond_t *cond) +{ + return pthread_cond_wait(&cond->id, &cond->lock); +} + +int +cond_timedwait(cond_t *cond, const struct timespec *abstime) +{ + return pthread_cond_timedwait(&cond->id, &cond->lock, abstime); +} + +int +cond_destroy(cond_t *cond) +{ + return pthread_cond_destroy(&cond->id); +} diff --git a/server/thread.h b/server/thread.h new file mode 100644 index 0000000..0aadef4 --- /dev/null +++ b/server/thread.h @@ -0,0 +1,49 @@ +/* $Id: thread.h,v 1.5 2000/03/15 00:09:25 shmit Exp $ */ + +#ifndef THREAD_H +# define THREAD_H + +#include "conf.h" + +#include <pthread.h> + +typedef pthread_t thread_id; +typedef pthread_mutex_t mutex_t; + +struct _rwlock { + mutex_t lock; + int state; + pthread_cond_t read_sig; + pthread_cond_t write_sig; + int blocked_writers; +}; +typedef struct _rwlock rw_mutex_t; + +struct thread { + void *(*thread_func)(void *arg); + pthread_t id; +}; +typedef struct thread thread_t; + +struct cond { + pthread_cond_t id; + mutex_t lock; +}; +typedef struct cond cond_t; + +int thread_new(thread_t *thread, void *(*thread_func)(void *), void *arg); +void thread_kill(thread_t *thread); +int thread_reload(thread_t *thread); +int mutex_new(mutex_t *lock); +int mutex_lock(mutex_t *lock); +int mutex_unlock(mutex_t *lock); +int rw_mutex_new(rw_mutex_t *lock); +int rw_mutex_read_lock(rw_mutex_t *lock); +int rw_mutex_write_lock(rw_mutex_t *lock); +int rw_mutex_unlock(rw_mutex_t *lock); +int cond_new(cond_t *cond); +int cond_signal(cond_t *cond); +int cond_wait(cond_t *cond); +int cond_timedwait(cond_t *cond, const struct timespec *abstime); +int cond_destroy(cond_t *cond); +#endif diff --git a/tests/.cvsignore b/tests/.cvsignore new file mode 100644 index 0000000..0d898eb --- /dev/null +++ b/tests/.cvsignore @@ -0,0 +1,14 @@ +getnast +killnast +randnast +statnast +stressnast +mtstressnast +updnast +.pure +*.o +*.so +*.a +*.core +*.gmon +tags diff --git a/tests/.pure b/tests/.pure new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/.pure diff --git a/tests/.svn/README.txt b/tests/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/tests/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/tests/.svn/empty-file b/tests/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/.svn/empty-file diff --git a/tests/.svn/entries b/tests/.svn/entries new file mode 100644 index 0000000..01b7881 --- /dev/null +++ b/tests/.svn/entries @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk/tests" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + committed-rev="1" + name="updnast.c" + text-time="2005-12-24T00:00:46.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="ec289f72dcd13681439581954425d2d7" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:45.000000Z"/> +<entry + committed-rev="1" + name="killnast.c" + text-time="2005-12-24T00:00:46.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="13334e900d0e0f5d00ecf81e44a822b8" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:45.000000Z"/> +<entry + committed-rev="1" + name="statnast.c" + text-time="2005-12-24T00:00:46.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="13334e900d0e0f5d00ecf81e44a822b8" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:45.000000Z"/> +<entry + committed-rev="1" + name="getnast.c" + text-time="2005-12-24T00:00:46.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="ae2b450a4fa8d55def3e7d3d07371a2d" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:45.000000Z"/> +<entry + committed-rev="1" + name="getass.c" + text-time="2005-12-24T00:00:46.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="9f8a0bb66ec1fa1c1666da52970b7a9e" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:45.000000Z"/> +<entry + committed-rev="1" + name=".pure" + text-time="2005-12-24T00:00:46.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="d41d8cd98f00b204e9800998ecf8427e" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:45.000000Z"/> +<entry + committed-rev="1" + name="stressnast.c" + text-time="2005-12-24T00:00:47.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="643dd30bf90282dca1ed92de6907c514" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:45.000000Z"/> +<entry + committed-rev="1" + name="mtstressnast.c" + text-time="2005-12-24T00:00:47.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="f71ab9f13fcc9bed6839e266a6e9244a" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:45.000000Z"/> +<entry + committed-rev="1" + name="randnast.c" + text-time="2005-12-24T00:00:47.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="a33465d2e807e9d630a323e5bde5609a" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:45.000000Z"/> +<entry + committed-rev="1" + name="mtstressass.c" + text-time="2005-12-24T00:00:47.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="771bd88ed8a02cdd13dbd88fdf522e81" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:46.000000Z"/> +<entry + committed-rev="1" + name=".cvsignore" + text-time="2005-12-24T00:00:47.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="98e1fd021c8da0a3b45a423374a6c51c" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:46.000000Z"/> +<entry + committed-rev="1" + name="Makefile" + text-time="2005-12-24T00:00:47.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="905fa6a41631a2e8c01087a110ec4518" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:46.000000Z"/> +</wc-entries> diff --git a/tests/.svn/format b/tests/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/tests/.svn/format @@ -0,0 +1 @@ +4 diff --git a/tests/.svn/prop-base/.cvsignore.svn-base b/tests/.svn/prop-base/.cvsignore.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/.cvsignore.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/prop-base/.pure.svn-base b/tests/.svn/prop-base/.pure.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/.pure.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/prop-base/Makefile.svn-base b/tests/.svn/prop-base/Makefile.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/Makefile.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/prop-base/getass.c.svn-base b/tests/.svn/prop-base/getass.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/getass.c.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/prop-base/getnast.c.svn-base b/tests/.svn/prop-base/getnast.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/getnast.c.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/prop-base/killnast.c.svn-base b/tests/.svn/prop-base/killnast.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/killnast.c.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/prop-base/mtstressass.c.svn-base b/tests/.svn/prop-base/mtstressass.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/mtstressass.c.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/prop-base/mtstressnast.c.svn-base b/tests/.svn/prop-base/mtstressnast.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/mtstressnast.c.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/prop-base/randnast.c.svn-base b/tests/.svn/prop-base/randnast.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/randnast.c.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/prop-base/statnast.c.svn-base b/tests/.svn/prop-base/statnast.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/statnast.c.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/prop-base/stressnast.c.svn-base b/tests/.svn/prop-base/stressnast.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/stressnast.c.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/prop-base/updnast.c.svn-base b/tests/.svn/prop-base/updnast.c.svn-base new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/prop-base/updnast.c.svn-base @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/.cvsignore.svn-work b/tests/.svn/props/.cvsignore.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/.cvsignore.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/.pure.svn-work b/tests/.svn/props/.pure.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/.pure.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/Makefile.svn-work b/tests/.svn/props/Makefile.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/Makefile.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/getass.c.svn-work b/tests/.svn/props/getass.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/getass.c.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/getnast.c.svn-work b/tests/.svn/props/getnast.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/getnast.c.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/killnast.c.svn-work b/tests/.svn/props/killnast.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/killnast.c.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/mtstressass.c.svn-work b/tests/.svn/props/mtstressass.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/mtstressass.c.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/mtstressnast.c.svn-work b/tests/.svn/props/mtstressnast.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/mtstressnast.c.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/randnast.c.svn-work b/tests/.svn/props/randnast.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/randnast.c.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/statnast.c.svn-work b/tests/.svn/props/statnast.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/statnast.c.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/stressnast.c.svn-work b/tests/.svn/props/stressnast.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/stressnast.c.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/props/updnast.c.svn-work b/tests/.svn/props/updnast.c.svn-work new file mode 100644 index 0000000..dce2c1d --- /dev/null +++ b/tests/.svn/props/updnast.c.svn-work @@ -0,0 +1 @@ +END diff --git a/tests/.svn/text-base/.cvsignore.svn-base b/tests/.svn/text-base/.cvsignore.svn-base new file mode 100644 index 0000000..0d898eb --- /dev/null +++ b/tests/.svn/text-base/.cvsignore.svn-base @@ -0,0 +1,14 @@ +getnast +killnast +randnast +statnast +stressnast +mtstressnast +updnast +.pure +*.o +*.so +*.a +*.core +*.gmon +tags diff --git a/tests/.svn/text-base/.pure.svn-base b/tests/.svn/text-base/.pure.svn-base new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/.svn/text-base/.pure.svn-base diff --git a/tests/.svn/text-base/Makefile.svn-base b/tests/.svn/text-base/Makefile.svn-base new file mode 100644 index 0000000..8c2cd69 --- /dev/null +++ b/tests/.svn/text-base/Makefile.svn-base @@ -0,0 +1,46 @@ +# $Id: Makefile,v 1.15 2000/12/27 06:51:51 shmit Exp $ + +LIBASS= ../client/libnast.a + +tclients: getnast statnast stressnast randnast mtstressnast updnast \ + killnast + +GETOBJS= getnast.o +getnast: ${GETOBJS} + ${PURIFY} ${CC} -o $@ ${GETOBJS} ${LIBASS} ${LIBS} + +STATOBJS= statnast.o +statnast: ${STATOBJS} + ${PURIFY} ${CC} -o $@ ${STATOBJS} ${LIBASS} ${LIBS} + +STRESSOBJS= stressnast.o +stressnast: ${STRESSOBJS} + ${PURIFY} ${CC} -o $@ ${STRESSOBJS} ${LIBASS} ${LIBS} + +RANDOBJS= randnast.o +randnast: ${RANDOBJS} + ${PURIFY} ${CC} -o $@ ${RANDOBJS} ${LIBASS} ${LIBS} + +MTSTRESSOBJS= mtstressnast.o +mtstressnast: ${MTSTRESSOBJS} + ${PURIFY} ${CC} -o $@ ${MTSTRESSOBJS} ${LIBASS} ${LIBS} + +UPDOBJS= updnast.o +updnast: ${UPDOBJS} + ${PURIFY} ${CC} -o $@ ${UPDOBJS} ${LIBASS} ${LIBS} + +KILLOBJS= killnast.o +killnast: ${KILLOBJS} + ${PURIFY} ${CC} -o $@ ${KILLOBJS} ${LIBASS} ${LIBS} + +# +# Dependencies +# +getnast.o: ../include/nastd.h +statnast.o: ../include/nastd.h +stressnast.o: ../include/nastd.h +randnast.o: ../include/nastd.h +mtstressnast.o: ../include/nastd.h + +MKDIR= ../Makefiles +include ${MKDIR}/build diff --git a/tests/.svn/text-base/getass.c.svn-base b/tests/.svn/text-base/getass.c.svn-base new file mode 100644 index 0000000..7f81bf8 --- /dev/null +++ b/tests/.svn/text-base/getass.c.svn-base @@ -0,0 +1,59 @@ +#include <assd.h> + +#include <stdio.h> +#include <stdlib.h> + +int +main(int argc, char *argv[]) +{ + assh *asshole; + ass_array *aa; + ass_options opts; + int i, rc; + + if (argc != 2) { + printf("Usage: %s query\n", argv[0]); + return 1; + } + + asshole = ass_sphincter_new(); + if (asshole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to asshole.\n"); + return 2; + } + + /* Get the default options. */ + rc = ass_options_get(asshole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get options: %s.\n", + ass_errmsg(asshole)); + ass_sphincter_close(asshole); + return 2; + } + + /* Add more fallthrough threads. */ + opts.fallthrough_threads = 5; + rc = ass_options_set(asshole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't set options: %s.\n", + ass_errmsg(asshole)); + ass_sphincter_close(asshole); + return 2; + } + + rc = ass_get(asshole, argv[1]); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't perform query: %s.\n", + ass_errmsg(asshole)); + ass_sphincter_close(asshole); + return 2; + } + + aa = ass_get_result(asshole); + for (i = 0; i < aa->nitems; i++) + printf("Result[%d]: `%s'\n", i, aa->items[i]->strdata); + ass_free_result(aa); + + ass_sphincter_close(asshole); + return 0; +} diff --git a/tests/.svn/text-base/getnast.c.svn-base b/tests/.svn/text-base/getnast.c.svn-base new file mode 100644 index 0000000..904c01f --- /dev/null +++ b/tests/.svn/text-base/getnast.c.svn-base @@ -0,0 +1,64 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> + +char *progname; + +void +usage() +{ + fprintf(stderr, "Usage: %s [-s socket] query\n", progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char *sock_n; + nasth *nasthole; + nast_array *aa; + char ch; + int i, rc; + + progname = strrchr(argv[0], '/'); + if (!progname) + progname = argv[0]; + else + progname++; + + sock_n = NULL; + while ((ch = getopt(argc, argv, "s:")) != -1) { + switch (ch) { + case 's': + sock_n = optarg; + break; + default: + usage(); + /* NOTREACHED */ + } + } + + nasthole = nast_sphincter_new(sock_n); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + rc = nast_get(nasthole, argv[argc-1]); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't perform query: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + aa = nast_get_result(nasthole); + for (i = 0; i < aa->nitems; i++) + printf("Result[%d]: `%s'\n", i, aa->items[i]->strdata); + nast_free_result(aa); + + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/.svn/text-base/killnast.c.svn-base b/tests/.svn/text-base/killnast.c.svn-base new file mode 100644 index 0000000..7c06dee --- /dev/null +++ b/tests/.svn/text-base/killnast.c.svn-base @@ -0,0 +1,39 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> + +int +main(int argc, char *argv[]) +{ + nasth *nasthole; + nast_array *aa; + int i, rc; + + if (argc != 1) { + printf("Usage: %s\n", argv[0]); + return 1; + } + + nasthole = nast_sphincter_new(NULL); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + rc = nast_stats(nasthole); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get stats: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + aa = nast_get_result(nasthole); + for (i = 0; i < aa->nitems; i++) + printf("%s\n", aa->items[i]->strdata); + nast_free_result(aa); + + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/.svn/text-base/mtstressass.c.svn-base b/tests/.svn/text-base/mtstressass.c.svn-base new file mode 100644 index 0000000..1a4c2e1 --- /dev/null +++ b/tests/.svn/text-base/mtstressass.c.svn-base @@ -0,0 +1,95 @@ +#include <assd.h> + +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> + +#define NTHREADS 10 + +assh *asshole; +char *username; + +void * +io_looper(void *arg) +{ + struct timeval before, after; + ass_options opts; + int i, rc; + + for (;;) { + /* Get the default options. */ + rc = ass_options_get(asshole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get options: %s.\n", + ass_errmsg(asshole)); + return NULL; + } + + /* Add more fallthrough threads. */ + opts.fallthrough_threads = 5; + rc = ass_options_set(asshole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't set options: %s.\n", + ass_errmsg(asshole)); + return NULL; + } + + for (i = 0; i < 10; i++) { + gettimeofday(&before, NULL); + rc = ass_get(asshole, username); + gettimeofday(&after, NULL); + if (rc == -1) { + if (ass_geterr(asshole) == ASS_TIMEDOUT) { + fprintf(stderr, + "ERROR: response timed out.\n"); + continue; + } + fprintf(stderr, + "ERROR: Couldn't perform query: %s.\n", + ass_errmsg(asshole)); + return NULL; + } + + after.tv_sec -= before.tv_sec; + after.tv_usec -= before.tv_usec; + if (after.tv_usec < 0) { + after.tv_sec--; + after.tv_usec += 1000000; + } + fprintf(stderr, "Request time: %2ld.%06ld seconds.\n", + after.tv_sec, after.tv_usec); + } + } +} + +int +main(int argc, char *argv[]) +{ + pthread_t tids[NTHREADS]; + int i; + + if (argc != 2) { + printf("Usage: %s query\n", argv[0]); + return 1; + } + username = argv[1]; + + asshole = ass_sphincter_new(); + if (asshole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to asshole.\n"); + return 2; + } + + for (i = 0; i < NTHREADS; i++) + pthread_create(&tids[i], NULL, io_looper, NULL); + + for (i = 0; i < NTHREADS; i++) + pthread_join(tids[i], NULL); + + ass_sphincter_close(asshole); + return 0; +} diff --git a/tests/.svn/text-base/mtstressnast.c.svn-base b/tests/.svn/text-base/mtstressnast.c.svn-base new file mode 100644 index 0000000..913312e --- /dev/null +++ b/tests/.svn/text-base/mtstressnast.c.svn-base @@ -0,0 +1,77 @@ +#include <nastd.h> + +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> + +#define NTHREADS 10 + +nasth *nasthole; +char *username; + +void * +io_looper(void *arg) +{ + struct timeval before, after; + int i, rc; + + for (;;) { + for (i = 0; i < 10; i++) { + gettimeofday(&before, NULL); + rc = nast_get(nasthole, username); + gettimeofday(&after, NULL); + if (rc == -1) { + if (nast_geterr(nasthole) == NAST_TIMEDOUT) { + fprintf(stderr, + "ERROR: response timed out.\n"); + continue; + } + fprintf(stderr, + "ERROR: Couldn't perform query: %s.\n", + nast_errmsg(nasthole)); + return NULL; + } + + after.tv_sec -= before.tv_sec; + after.tv_usec -= before.tv_usec; + if (after.tv_usec < 0) { + after.tv_sec--; + after.tv_usec += 1000000; + } + fprintf(stderr, "Request time: %2ld.%06ld seconds.\n", + after.tv_sec, after.tv_usec); + } + } +} + +int +main(int argc, char *argv[]) +{ + pthread_t tids[NTHREADS]; + int i; + + if (argc != 2) { + printf("Usage: %s query\n", argv[0]); + return 1; + } + username = argv[1]; + + nasthole = nast_sphincter_new(NULL); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + for (i = 0; i < NTHREADS; i++) + pthread_create(&tids[i], NULL, io_looper, NULL); + + for (i = 0; i < NTHREADS; i++) + pthread_join(tids[i], NULL); + + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/.svn/text-base/randnast.c.svn-base b/tests/.svn/text-base/randnast.c.svn-base new file mode 100644 index 0000000..dd39fc6 --- /dev/null +++ b/tests/.svn/text-base/randnast.c.svn-base @@ -0,0 +1,69 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> + +char letters[] = "abcdefghijklmnopqrstuvwxyz0123456789-_."; + +int +main(int argc, char *argv[]) +{ + nasth *nasthole; + struct timeval before, after; + nast_options opts; + int i, rc; + + nasthole = nast_sphincter_new(NULL); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + srand(time(NULL)); + + for (;;) { + /* Get the default options. */ + rc = nast_options_get(nasthole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get options: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + for (i = 0; i < 10; i++) { + char uname[32]; + int i, maxlen; + + maxlen = rand() % sizeof(uname); + for (i = 0; i < maxlen-1; i++) + uname[i] = letters[rand() % sizeof(letters)]; + uname[maxlen] = '\0'; + + gettimeofday(&before, NULL); + rc = nast_get(nasthole, uname); + gettimeofday(&after, NULL); + if (rc == -1) { + fprintf(stderr, + "ERROR: Couldn't perform query: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + after.tv_sec -= before.tv_sec; + after.tv_usec -= before.tv_usec; + if (after.tv_usec < 0) { + after.tv_sec--; + after.tv_usec += 1000000; + } + fprintf(stderr, "Request time: %2ld.%06ld seconds.\n", + after.tv_sec, after.tv_usec); + } + } + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/.svn/text-base/statnast.c.svn-base b/tests/.svn/text-base/statnast.c.svn-base new file mode 100644 index 0000000..7c06dee --- /dev/null +++ b/tests/.svn/text-base/statnast.c.svn-base @@ -0,0 +1,39 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> + +int +main(int argc, char *argv[]) +{ + nasth *nasthole; + nast_array *aa; + int i, rc; + + if (argc != 1) { + printf("Usage: %s\n", argv[0]); + return 1; + } + + nasthole = nast_sphincter_new(NULL); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + rc = nast_stats(nasthole); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get stats: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + aa = nast_get_result(nasthole); + for (i = 0; i < aa->nitems; i++) + printf("%s\n", aa->items[i]->strdata); + nast_free_result(aa); + + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/.svn/text-base/stressnast.c.svn-base b/tests/.svn/text-base/stressnast.c.svn-base new file mode 100644 index 0000000..ad17a51 --- /dev/null +++ b/tests/.svn/text-base/stressnast.c.svn-base @@ -0,0 +1,60 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> + +int +main(int argc, char *argv[]) +{ + nasth *nasthole; + struct timeval before, after; + nast_options opts; + int i, rc; + + if (argc != 2) { + printf("Usage: %s query\n", argv[0]); + return 1; + } + + nasthole = nast_sphincter_new(NULL); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + for (;;) { + /* Get the default options. */ + rc = nast_options_get(nasthole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get options: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + for (i = 0; i < 10; i++) { + gettimeofday(&before, NULL); + rc = nast_get(nasthole, argv[1]); + gettimeofday(&after, NULL); + if (rc == -1) { + fprintf(stderr, + "ERROR: Couldn't perform query: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + after.tv_sec -= before.tv_sec; + after.tv_usec -= before.tv_usec; + if (after.tv_usec < 0) { + after.tv_sec--; + after.tv_usec += 1000000; + } + fprintf(stderr, "Request time: %2ld.%06ld seconds.\n", + after.tv_sec, after.tv_usec); + } + } + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/.svn/text-base/updnast.c.svn-base b/tests/.svn/text-base/updnast.c.svn-base new file mode 100644 index 0000000..9acef66 --- /dev/null +++ b/tests/.svn/text-base/updnast.c.svn-base @@ -0,0 +1,80 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> + +char *progname; + +void +usage() +{ + fprintf(stderr, "Usage: %s [-s socket] query\n", progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char *sock_n; + nasth *nasthole; + nast_array *aa; + char ch; + int i, rc; + + progname = strrchr(argv[0], '/'); + if (!progname) + progname = argv[0]; + else + progname++; + + sock_n = NULL; + while ((ch = getopt(argc, argv, "s:")) != -1) { + switch (ch) { + case 's': + sock_n = optarg; + break; + default: + usage(); + /* NOTREACHED */ + } + } + + nasthole = nast_sphincter_new(sock_n); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + aa = nast_array_new(); + if (aa == NULL) { + fprintf(stderr, "ERROR: Couldn't create array.\n"); + return 3; + } + + for (i = optind+1; i < argc; i++) + nast_array_add(aa, strlen(argv[i]), argv[i]); + + rc = nast_upd(nasthole, argv[optind], aa); + nast_array_delete(aa); + + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't perform update: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + aa = nast_get_result(nasthole); + if (aa->nitems == 0 || (aa->nitems == 1 && + aa->items[0]->strlen == 0)) + printf("Update for %s succeeded.\n", argv[optind]); + else { + for (i = 0; i < aa->nitems; i++) + printf("Result[%d]: `%s'\n", i, aa->items[i]->strdata); + } + nast_free_result(aa); + + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..8c2cd69 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,46 @@ +# $Id: Makefile,v 1.15 2000/12/27 06:51:51 shmit Exp $ + +LIBASS= ../client/libnast.a + +tclients: getnast statnast stressnast randnast mtstressnast updnast \ + killnast + +GETOBJS= getnast.o +getnast: ${GETOBJS} + ${PURIFY} ${CC} -o $@ ${GETOBJS} ${LIBASS} ${LIBS} + +STATOBJS= statnast.o +statnast: ${STATOBJS} + ${PURIFY} ${CC} -o $@ ${STATOBJS} ${LIBASS} ${LIBS} + +STRESSOBJS= stressnast.o +stressnast: ${STRESSOBJS} + ${PURIFY} ${CC} -o $@ ${STRESSOBJS} ${LIBASS} ${LIBS} + +RANDOBJS= randnast.o +randnast: ${RANDOBJS} + ${PURIFY} ${CC} -o $@ ${RANDOBJS} ${LIBASS} ${LIBS} + +MTSTRESSOBJS= mtstressnast.o +mtstressnast: ${MTSTRESSOBJS} + ${PURIFY} ${CC} -o $@ ${MTSTRESSOBJS} ${LIBASS} ${LIBS} + +UPDOBJS= updnast.o +updnast: ${UPDOBJS} + ${PURIFY} ${CC} -o $@ ${UPDOBJS} ${LIBASS} ${LIBS} + +KILLOBJS= killnast.o +killnast: ${KILLOBJS} + ${PURIFY} ${CC} -o $@ ${KILLOBJS} ${LIBASS} ${LIBS} + +# +# Dependencies +# +getnast.o: ../include/nastd.h +statnast.o: ../include/nastd.h +stressnast.o: ../include/nastd.h +randnast.o: ../include/nastd.h +mtstressnast.o: ../include/nastd.h + +MKDIR= ../Makefiles +include ${MKDIR}/build diff --git a/tests/getass.c b/tests/getass.c new file mode 100644 index 0000000..7f81bf8 --- /dev/null +++ b/tests/getass.c @@ -0,0 +1,59 @@ +#include <assd.h> + +#include <stdio.h> +#include <stdlib.h> + +int +main(int argc, char *argv[]) +{ + assh *asshole; + ass_array *aa; + ass_options opts; + int i, rc; + + if (argc != 2) { + printf("Usage: %s query\n", argv[0]); + return 1; + } + + asshole = ass_sphincter_new(); + if (asshole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to asshole.\n"); + return 2; + } + + /* Get the default options. */ + rc = ass_options_get(asshole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get options: %s.\n", + ass_errmsg(asshole)); + ass_sphincter_close(asshole); + return 2; + } + + /* Add more fallthrough threads. */ + opts.fallthrough_threads = 5; + rc = ass_options_set(asshole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't set options: %s.\n", + ass_errmsg(asshole)); + ass_sphincter_close(asshole); + return 2; + } + + rc = ass_get(asshole, argv[1]); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't perform query: %s.\n", + ass_errmsg(asshole)); + ass_sphincter_close(asshole); + return 2; + } + + aa = ass_get_result(asshole); + for (i = 0; i < aa->nitems; i++) + printf("Result[%d]: `%s'\n", i, aa->items[i]->strdata); + ass_free_result(aa); + + ass_sphincter_close(asshole); + return 0; +} diff --git a/tests/getnast.c b/tests/getnast.c new file mode 100644 index 0000000..904c01f --- /dev/null +++ b/tests/getnast.c @@ -0,0 +1,64 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> + +char *progname; + +void +usage() +{ + fprintf(stderr, "Usage: %s [-s socket] query\n", progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char *sock_n; + nasth *nasthole; + nast_array *aa; + char ch; + int i, rc; + + progname = strrchr(argv[0], '/'); + if (!progname) + progname = argv[0]; + else + progname++; + + sock_n = NULL; + while ((ch = getopt(argc, argv, "s:")) != -1) { + switch (ch) { + case 's': + sock_n = optarg; + break; + default: + usage(); + /* NOTREACHED */ + } + } + + nasthole = nast_sphincter_new(sock_n); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + rc = nast_get(nasthole, argv[argc-1]); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't perform query: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + aa = nast_get_result(nasthole); + for (i = 0; i < aa->nitems; i++) + printf("Result[%d]: `%s'\n", i, aa->items[i]->strdata); + nast_free_result(aa); + + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/killnast.c b/tests/killnast.c new file mode 100644 index 0000000..7c06dee --- /dev/null +++ b/tests/killnast.c @@ -0,0 +1,39 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> + +int +main(int argc, char *argv[]) +{ + nasth *nasthole; + nast_array *aa; + int i, rc; + + if (argc != 1) { + printf("Usage: %s\n", argv[0]); + return 1; + } + + nasthole = nast_sphincter_new(NULL); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + rc = nast_stats(nasthole); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get stats: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + aa = nast_get_result(nasthole); + for (i = 0; i < aa->nitems; i++) + printf("%s\n", aa->items[i]->strdata); + nast_free_result(aa); + + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/mtstressass.c b/tests/mtstressass.c new file mode 100644 index 0000000..1a4c2e1 --- /dev/null +++ b/tests/mtstressass.c @@ -0,0 +1,95 @@ +#include <assd.h> + +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> + +#define NTHREADS 10 + +assh *asshole; +char *username; + +void * +io_looper(void *arg) +{ + struct timeval before, after; + ass_options opts; + int i, rc; + + for (;;) { + /* Get the default options. */ + rc = ass_options_get(asshole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get options: %s.\n", + ass_errmsg(asshole)); + return NULL; + } + + /* Add more fallthrough threads. */ + opts.fallthrough_threads = 5; + rc = ass_options_set(asshole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't set options: %s.\n", + ass_errmsg(asshole)); + return NULL; + } + + for (i = 0; i < 10; i++) { + gettimeofday(&before, NULL); + rc = ass_get(asshole, username); + gettimeofday(&after, NULL); + if (rc == -1) { + if (ass_geterr(asshole) == ASS_TIMEDOUT) { + fprintf(stderr, + "ERROR: response timed out.\n"); + continue; + } + fprintf(stderr, + "ERROR: Couldn't perform query: %s.\n", + ass_errmsg(asshole)); + return NULL; + } + + after.tv_sec -= before.tv_sec; + after.tv_usec -= before.tv_usec; + if (after.tv_usec < 0) { + after.tv_sec--; + after.tv_usec += 1000000; + } + fprintf(stderr, "Request time: %2ld.%06ld seconds.\n", + after.tv_sec, after.tv_usec); + } + } +} + +int +main(int argc, char *argv[]) +{ + pthread_t tids[NTHREADS]; + int i; + + if (argc != 2) { + printf("Usage: %s query\n", argv[0]); + return 1; + } + username = argv[1]; + + asshole = ass_sphincter_new(); + if (asshole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to asshole.\n"); + return 2; + } + + for (i = 0; i < NTHREADS; i++) + pthread_create(&tids[i], NULL, io_looper, NULL); + + for (i = 0; i < NTHREADS; i++) + pthread_join(tids[i], NULL); + + ass_sphincter_close(asshole); + return 0; +} diff --git a/tests/mtstressnast.c b/tests/mtstressnast.c new file mode 100644 index 0000000..913312e --- /dev/null +++ b/tests/mtstressnast.c @@ -0,0 +1,77 @@ +#include <nastd.h> + +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> + +#define NTHREADS 10 + +nasth *nasthole; +char *username; + +void * +io_looper(void *arg) +{ + struct timeval before, after; + int i, rc; + + for (;;) { + for (i = 0; i < 10; i++) { + gettimeofday(&before, NULL); + rc = nast_get(nasthole, username); + gettimeofday(&after, NULL); + if (rc == -1) { + if (nast_geterr(nasthole) == NAST_TIMEDOUT) { + fprintf(stderr, + "ERROR: response timed out.\n"); + continue; + } + fprintf(stderr, + "ERROR: Couldn't perform query: %s.\n", + nast_errmsg(nasthole)); + return NULL; + } + + after.tv_sec -= before.tv_sec; + after.tv_usec -= before.tv_usec; + if (after.tv_usec < 0) { + after.tv_sec--; + after.tv_usec += 1000000; + } + fprintf(stderr, "Request time: %2ld.%06ld seconds.\n", + after.tv_sec, after.tv_usec); + } + } +} + +int +main(int argc, char *argv[]) +{ + pthread_t tids[NTHREADS]; + int i; + + if (argc != 2) { + printf("Usage: %s query\n", argv[0]); + return 1; + } + username = argv[1]; + + nasthole = nast_sphincter_new(NULL); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + for (i = 0; i < NTHREADS; i++) + pthread_create(&tids[i], NULL, io_looper, NULL); + + for (i = 0; i < NTHREADS; i++) + pthread_join(tids[i], NULL); + + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/randnast.c b/tests/randnast.c new file mode 100644 index 0000000..dd39fc6 --- /dev/null +++ b/tests/randnast.c @@ -0,0 +1,69 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> + +char letters[] = "abcdefghijklmnopqrstuvwxyz0123456789-_."; + +int +main(int argc, char *argv[]) +{ + nasth *nasthole; + struct timeval before, after; + nast_options opts; + int i, rc; + + nasthole = nast_sphincter_new(NULL); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + srand(time(NULL)); + + for (;;) { + /* Get the default options. */ + rc = nast_options_get(nasthole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get options: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + for (i = 0; i < 10; i++) { + char uname[32]; + int i, maxlen; + + maxlen = rand() % sizeof(uname); + for (i = 0; i < maxlen-1; i++) + uname[i] = letters[rand() % sizeof(letters)]; + uname[maxlen] = '\0'; + + gettimeofday(&before, NULL); + rc = nast_get(nasthole, uname); + gettimeofday(&after, NULL); + if (rc == -1) { + fprintf(stderr, + "ERROR: Couldn't perform query: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + after.tv_sec -= before.tv_sec; + after.tv_usec -= before.tv_usec; + if (after.tv_usec < 0) { + after.tv_sec--; + after.tv_usec += 1000000; + } + fprintf(stderr, "Request time: %2ld.%06ld seconds.\n", + after.tv_sec, after.tv_usec); + } + } + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/statnast.c b/tests/statnast.c new file mode 100644 index 0000000..7c06dee --- /dev/null +++ b/tests/statnast.c @@ -0,0 +1,39 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> + +int +main(int argc, char *argv[]) +{ + nasth *nasthole; + nast_array *aa; + int i, rc; + + if (argc != 1) { + printf("Usage: %s\n", argv[0]); + return 1; + } + + nasthole = nast_sphincter_new(NULL); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + rc = nast_stats(nasthole); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get stats: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + aa = nast_get_result(nasthole); + for (i = 0; i < aa->nitems; i++) + printf("%s\n", aa->items[i]->strdata); + nast_free_result(aa); + + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/stressnast.c b/tests/stressnast.c new file mode 100644 index 0000000..ad17a51 --- /dev/null +++ b/tests/stressnast.c @@ -0,0 +1,60 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> + +int +main(int argc, char *argv[]) +{ + nasth *nasthole; + struct timeval before, after; + nast_options opts; + int i, rc; + + if (argc != 2) { + printf("Usage: %s query\n", argv[0]); + return 1; + } + + nasthole = nast_sphincter_new(NULL); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + for (;;) { + /* Get the default options. */ + rc = nast_options_get(nasthole, &opts); + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't get options: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + for (i = 0; i < 10; i++) { + gettimeofday(&before, NULL); + rc = nast_get(nasthole, argv[1]); + gettimeofday(&after, NULL); + if (rc == -1) { + fprintf(stderr, + "ERROR: Couldn't perform query: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + after.tv_sec -= before.tv_sec; + after.tv_usec -= before.tv_usec; + if (after.tv_usec < 0) { + after.tv_sec--; + after.tv_usec += 1000000; + } + fprintf(stderr, "Request time: %2ld.%06ld seconds.\n", + after.tv_sec, after.tv_usec); + } + } + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tests/updnast.c b/tests/updnast.c new file mode 100644 index 0000000..9acef66 --- /dev/null +++ b/tests/updnast.c @@ -0,0 +1,80 @@ +#include <nastd.h> + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> + +char *progname; + +void +usage() +{ + fprintf(stderr, "Usage: %s [-s socket] query\n", progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char *sock_n; + nasth *nasthole; + nast_array *aa; + char ch; + int i, rc; + + progname = strrchr(argv[0], '/'); + if (!progname) + progname = argv[0]; + else + progname++; + + sock_n = NULL; + while ((ch = getopt(argc, argv, "s:")) != -1) { + switch (ch) { + case 's': + sock_n = optarg; + break; + default: + usage(); + /* NOTREACHED */ + } + } + + nasthole = nast_sphincter_new(sock_n); + if (nasthole == NULL) { + fprintf(stderr, "ERROR: Couldn't connect to nasthole.\n"); + return 2; + } + + aa = nast_array_new(); + if (aa == NULL) { + fprintf(stderr, "ERROR: Couldn't create array.\n"); + return 3; + } + + for (i = optind+1; i < argc; i++) + nast_array_add(aa, strlen(argv[i]), argv[i]); + + rc = nast_upd(nasthole, argv[optind], aa); + nast_array_delete(aa); + + if (rc == -1) { + fprintf(stderr, "ERROR: Couldn't perform update: %s.\n", + nast_errmsg(nasthole)); + nast_sphincter_close(nasthole); + return 2; + } + + aa = nast_get_result(nasthole); + if (aa->nitems == 0 || (aa->nitems == 1 && + aa->items[0]->strlen == 0)) + printf("Update for %s succeeded.\n", argv[optind]); + else { + for (i = 0; i < aa->nitems; i++) + printf("Result[%d]: `%s'\n", i, aa->items[i]->strdata); + } + nast_free_result(aa); + + nast_sphincter_close(nasthole); + return 0; +} diff --git a/tools/.svn/README.txt b/tools/.svn/README.txt new file mode 100644 index 0000000..271a8ce --- /dev/null +++ b/tools/.svn/README.txt @@ -0,0 +1,2 @@ +This is a Subversion working copy administrative directory. +Visit http://subversion.tigris.org/ for more information. diff --git a/tools/.svn/empty-file b/tools/.svn/empty-file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tools/.svn/empty-file diff --git a/tools/.svn/entries b/tools/.svn/entries new file mode 100644 index 0000000..af4e06f --- /dev/null +++ b/tools/.svn/entries @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<wc-entries + xmlns="svn:"> +<entry + committed-rev="1" + name="" + committed-date="2005-12-08T17:32:07.572093Z" + url="svn+ssh://coleridge/svn/nastd/trunk/tools" + last-author="bjc" + kind="dir" + uuid="2641c99b-6c07-0410-920d-927397d2d5d0" + revision="8"/> +<entry + committed-rev="1" + name="build" + text-time="2005-12-24T00:00:41.000000Z" + committed-date="2005-12-08T17:32:07.572093Z" + checksum="d0ede51e29bdfbd13a756fcd152bf8bd" + last-author="bjc" + kind="file" + prop-time="2005-12-24T00:00:41.000000Z"/> +</wc-entries> diff --git a/tools/.svn/format b/tools/.svn/format new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/tools/.svn/format @@ -0,0 +1 @@ +4 diff --git a/tools/.svn/prop-base/build.svn-base b/tools/.svn/prop-base/build.svn-base new file mode 100644 index 0000000..a669705 --- /dev/null +++ b/tools/.svn/prop-base/build.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 0 + +END diff --git a/tools/.svn/props/build.svn-work b/tools/.svn/props/build.svn-work new file mode 100644 index 0000000..a669705 --- /dev/null +++ b/tools/.svn/props/build.svn-work @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 0 + +END diff --git a/tools/.svn/text-base/build.svn-base b/tools/.svn/text-base/build.svn-base new file mode 100644 index 0000000..7a374f0 --- /dev/null +++ b/tools/.svn/text-base/build.svn-base @@ -0,0 +1,53 @@ +#!/bin/sh +# +# $Id: build,v 1.1.1.1 2000/02/16 23:32:47 shmit Exp $ + +os=`uname -s` +rev=`uname -r` +rev_major=`echo $rev | cut -d. -f1` + +case $os in +FreeBSD) + if [ $rev_major -ge 3 ]; then + target=freebsd + else + target=freebsd2 + fi + ;; +Linux) + target=linux + ;; +SunOS) + if [ $rev_major -ge 5 ]; then + target=solaris + else + target=sunos + fi + ;; +*) + echo "I don't know how to build for your platform, please poke" 1>&2 + echo "around in Makefiles/os and tools/build to get the server" 1>&2 + echo "to work on your platform." 1>&2 + exit 1 + ;; +esac + +# Figure out which make to use. +make=$1 && shift 1 + +# Clobber the target makefile if the target of the build is the Makefile. +if [ "$1" = "target" ]; then + rm -f Makefiles/os/target + echo "Setting build target to $target." + ln -s $target Makefiles/os/target && exit 0 + exit 1 +fi + +# Make sure the OS Makefile is in place. +if [ ! -f Makefiles/os/target ]; then + echo "Setting build target to $target." + ln -s $target Makefiles/os/target || exit 1 +fi + +# Now build the target. +$make MAKE=$make -f Makefiles/build $* diff --git a/tools/build b/tools/build new file mode 100755 index 0000000..7a374f0 --- /dev/null +++ b/tools/build @@ -0,0 +1,53 @@ +#!/bin/sh +# +# $Id: build,v 1.1.1.1 2000/02/16 23:32:47 shmit Exp $ + +os=`uname -s` +rev=`uname -r` +rev_major=`echo $rev | cut -d. -f1` + +case $os in +FreeBSD) + if [ $rev_major -ge 3 ]; then + target=freebsd + else + target=freebsd2 + fi + ;; +Linux) + target=linux + ;; +SunOS) + if [ $rev_major -ge 5 ]; then + target=solaris + else + target=sunos + fi + ;; +*) + echo "I don't know how to build for your platform, please poke" 1>&2 + echo "around in Makefiles/os and tools/build to get the server" 1>&2 + echo "to work on your platform." 1>&2 + exit 1 + ;; +esac + +# Figure out which make to use. +make=$1 && shift 1 + +# Clobber the target makefile if the target of the build is the Makefile. +if [ "$1" = "target" ]; then + rm -f Makefiles/os/target + echo "Setting build target to $target." + ln -s $target Makefiles/os/target && exit 0 + exit 1 +fi + +# Make sure the OS Makefile is in place. +if [ ! -f Makefiles/os/target ]; then + echo "Setting build target to $target." + ln -s $target Makefiles/os/target || exit 1 +fi + +# Now build the target. +$make MAKE=$make -f Makefiles/build $* |