diff options
154 files changed, 8788 insertions, 0 deletions
@@ -0,0 +1,107 @@ +0.2 Initial Release 1/13/97 + + Includes spo256-al2 server. Maintained by David Sugar + <dyfet@tycho.com>. + +0.2pl1 Patch Update 1/16/97 + + Updated build/dist and added config.dist. This should make for + better control of distribution sets off a live production system. + This also solves 'second level' production problems off a + distribution set. + + Updated build/instinit to allow automatic linkage of the speak.init + service script to a free 'S' slot in rc3.d. Instinit is now smarter + about how it handles startup script installation, especially for + Linux. Care with speak.init should still be taken for non-Linux + systems. + + Replaced missing config.c in sdk/std. + + Fixed vstat bug where it would fall-through into vmon code. + + Updated vmon to use more portable utent() routines instead of + directly accessing the utmp file. This was to improve portability. + + Updated vmon to use utmp routines to determine uptime if + /proc/uptime does not exist. This should help with porting + to non-Linux systems, or with Linux systems when 'proc' is + not installed. + + Made statfs() dependent code conditional, and active only + for linux, to prevent problems when compiling on non-Linux + operating systems. Code will need to be added to drive + external "df" image if no statfs() service is supported. + +0.2pl2 Patch Update 1/27/97 + + Found problem in tcpsocket.c, which would not compile correctly + on some sites. + + Added diag build script "Make diag" target to re-mail system + diagnostic reports. + + Added "config.diag" for "Make diag". + +0.3 Second Release 2/14/97 + + Changed sdk 'dev' stty support to improve stty setup operations. + This involved minor code changes to getspo.c. + + Changed sdk 'net' binding code to standardize handling of network + addresses passed as strings using getnetaddr(). + + The [interface] bind = option may now be used to restrict the + speak port to a specific subnet interface address. This + should keep the rest of the internet out of speak ports! + + Changed spo256 server to use a "character-state" parser in place + of the prior simplified token scanning routines. This is closer + to the original WorldVU server, and is implimented much more + cleanly. + + The server now also recognizes special "server" specific commands + that may be embedded in the output stream. These server commands + are prefixed with an <ESC> and appear inside <>'s. Server + commands allow some direct interaction with the server, such as + being able to force specific pronouniation rules. More advanced + devices (beyond the SPO) may someday make use of server commands + to force change of tone, inflection, or volume. + + The [vmon] settings in speak.conf have changes to support control + of timer intervals for monitoring system status. The new interval + option is meant for when we add mailbox and user login tracking. + This controls the interval for such short duration events, in + minutes. The 'frequency' option indicates how many times per + hour you want vmon to announce. Once is usually quite enough. + If you are upgrading, you will want to check the speak.conf + file in the distribution. + + Vmon can now watch for and notify when new mail arrives in + specified user accounts. This behavior is controlled with + the new [vmon] entries in speak.conf for 'maildir=' and + 'mailbox='. Maildir should point the mail spool directory + (typically /var/spool/mail) and one or more mailbox lines + can be used to list those user accounts you want to have + verbal mail notification for. + +1.0 + + The entire build and sdk process has been redone and unified for + improved portability. No functional changes have been made in the + application. The major difference, initially, is that, instead of + performing a "make config", one now executes ./config to start the + build process going for the package. + + We have also standardized 'config' around a hybrid file structure + that is fully consistent with the Linux file naming standard, can + comply with BSD file layouts, is compatible with most UNIX's, + and automatically recognizes secure TSW "Linux" release 1 and gnu/ + glib 2.x introduced file naming and ownership conventions. + Support for TSW-LR1 html documentation and software package + redistribution conventions are implied in the new 'config'. This + release will be available in source and binary rpm format for any + rpm managed Linux system. + + + @@ -0,0 +1,36 @@ +Copyright (c) 1997 Tycho Softworks. All rights reserved. + +This source is made freely available for public use, and may be +redistributed in source and/or binary forms, with or without +modification, provided that the following conditions are met: + +1. Redistributions of modified source code must retain all + original copyright notices when present. + +2. Redistributions of modified source code or binary archives + must include this license agreement unmodified. + +3. Neither the name of Tycho Softworks nor the names of it's + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +4. Where Berkeley (BSD) licensed source or header files may be used + within this distribution, such use is hereby acknowledged and + subject to the original terms and conditions as specified in + the comments of said specific source files. + +THIS SOFTWARE IS PROVIDED BY THE TYCHO SOFTWORKS ``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 TYCHO SOFTWORKS 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. + +Any comments or questions in regards to this license or that arise +from it's use may be addressed to "dyfet@tycho.com". + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..55dfe1b --- /dev/null +++ b/Makefile.in @@ -0,0 +1,75 @@ +# +# Top level project Makefile for "speak". +# $ProjectHeader: speak 0.4 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ +# Copyright (c) 1997 by Tycho Softworks. +# +# Targets: +# [none] default as 'make all' +# [all] create config if missing, then build all +# [install] build and install spo server and utils +# [dist] create distribution archive +# [web] build online (web) published distribution +# [clean] clean up a build +# [config] build initial configuration +# [reconfig] rebuild changed configuration +# [diag] send diagnostic e-mail +# [get] and [put] replicate source tree + +# Insert any default configuration values in CONFIGURE. + +CONFIGURE= + +# Internal use for source tree replication + +SOURCES = /mnt/share/source/shared/speak +EXCLUDE = --exclude Makefile --exclude config.cache +RSYNC = rsync -auSC $(EXCLUDE) + +all: config + @cd sdk/std ; make + @cd sdk/dev ; make + @cd sdk/net ; make + @cd sdk/other ; make + @cd sdk/proc ; make + @cd spo256 ; make + @cd utils ; make + +get: + $(RSYNC) $(SOURCES)/* . + ./config + +put: + $(RSYNC) * $(SOURCES) + +install: + @cd spo256 ; make install + @cd utils ; make install + +dist: + @cp -f /etc/speak.conf spo256 + @sdk/bin/dist $(DISTDIR) + +web: + @sdk/bin/disthtml $(HTMLDIR) $(MANDIR) + +clean: + @cd sdk/std ; make clean + @cd sdk/net ; make clean + @cd sdk/dev ; make clean + @cd sdk/other ; make clean + @cd sdk/proc ; make clean + @cd spo256 ; make clean + @cd utils ; make clean + @build/clean + +config: + @echo "Creating Speak Project Configuration ---" + @sdk/bin/config + +reconfig: + -@rm config.cache + @sdk/bin/config + +diag: + @sdk/bin/diag | mail -s "Speak Diagnostic Report" dyfet@tycho.com + diff --git a/README.FIRST b/README.FIRST new file mode 100644 index 0000000..37403ab --- /dev/null +++ b/README.FIRST @@ -0,0 +1,65 @@ +SPO256-AL2 based Text-to-Speech Network Services Version 0.2 + +This package comprises a new stand-alone release of the standard 'text to +speech' interface service and tools as first covered in the SPO article +appearing in Linux Journal, January 1997. Generic support for using the +SPO256-AL2 based board, and potentially other alternate network accessible +text-to-speech resources, is now more cleanly supported in a portable manner +that should allow use under virtually any UNIX'oid OS. This release +supersedes the initial WorldVU based source release originally described +in Linux Journal. + +This new release includes a new and portable SPO256 text-to-speech server, +some glue scripts for init.d in Linux to use the SPO as a normal system +'service', and many of the standard utilities re-written in a more +generic form. The new server should do a better job of parsing textual +documents into natural sounding speech as new rules for handling common +abbreviations and to improve word pacing have been added. + +The source for the SPO256-AL2 server is now more modular and more fully +documented. The utilities now include standard man pages. The server +now supports alternate forms of operation for use in client scripts. + +If you do not have the Linux Journal article in question, the SPO256 is +essentially a serial based text-to-speech board of limited utility. The +SPO256-AL2 (Vocoder) chip was originally used in many products, including +the Matel speak-and-spell(tm) toy, and offers limited text-to-speech +translation services. The SPO256 server augments the limited translation +capabilities of the SPO256 chipset and offers a network accessible resource +for text-to-speech notifications, such as system alerts, user logins, etc. + +This new server assumes a standard TCP 'service' has been defined in +/etc/services. You should edit the /etc/services file to include an entry +like the following (though a different port number may be used): + +speak 800/tcp # SPO256 text-to-speech network resource + +You will also need to copy speak.conf to /etc and modify it as needed. + +While the SPO256-AL2 is the primary hardware interface supported in this +package, other alternate text-to-speech devices may be added later that +will also use the "speak" port service. In particular, a re-implementation +of rsynth is being considered. Since the utilities talk to a standard +tcp port interface, they remain unchanged regardless of the underlying +hardware used to produce text-to-speech output. + +To build the software package, first run ./config. Config will genorate +the Makefiles. Config will then start 'make'. The configuration system +will attempt to identify the OS it is running under, compiler options, etc. +This may work under most UNIX operating systems, so the SPO package should +not be assumed to be a Linux-only utility. Once make completes successfully, +perform a 'make install'. This will update the /etc/services file and install +the application binaries. If you have difficulty with the new source +configuration tool, please review build/config.doc. + +Please examine the speak.conf and speak.init files, and relocate them as +needed. Further documentation may be found within the supplied man pages. +Comments may be addressed to David Sugar <dyfet@tycho.com>. The SPO256- +AL2 Text-to-Speech board ("Computalker") may be ordered through B&G Micro, +P.O. Box 280298, Dallas, TX 75228 (214) 271-5546. Linux Journal may be +found http://www.ssc.com/lj. + + + + + @@ -0,0 +1,25 @@ +Many things... + +* Build a "rsynth" based server. Change primary 'make' to request + server type, as in 'make rsynth', 'make spo256', or 'make utils', + the latter to build utilities only on a machine without it's own + server. + +* Add support for retrieving "index" status and time-sync rondeveus + by supporting a "inquire" sequence for the server to respond to. + Time-sync would be with "<drain>" server tag, which would force + the server to 'tcdrain' the port and then return a response. The + "<index>" tag would retrieve an index. Other 'tag' options for + volume control, pitch, inflection, etc, may also need to be added + for rsynth, although the SPO does not support these features. + +* Build spksnmpd for rule based verbalization of specific snmp trap + events. + +* Add user login monitoring to vmon. + +* Add external "df" code to vmon for systems that have no statfs() + call. + +* Build rpm package for speak. + @@ -0,0 +1,175 @@ +#!/bin/sh + +# +# Reload defaults +# + +BUILD=sdk +CONFIG=sdk/config.h + +if test -f config.cache ; then + . ./config.cache +fi +echo -n >config.cache + +if test -f config.pkg ; then + . ./config.pkg +fi + +# +# Load bindings +# + +if test -f config.pkg ; then + . ./config.pkg +fi + +if test -f config.make ; then + echo -n >config.make +fi + +if test -f $CONFIG ; then + echo -n >$CONFIG +fi + +if test -f $BUILD/bin/config.sub ; then + . $BUILD/bin/config.sub +fi + +BIND_OPTS='host' + +if test -z "$CONFIG_HOST" ; then + if test -d /usr/local/include ; then + CONFIG_HOST=/usr/local + fi + if test -d /usr/include ; then + CONFIG_HOST=/usr + fi +fi + +opt_host() { + CONFIG_HOST="$1" + return 0 +} + +if test ! -z "$BIND" ; then + for bind in $BIND ; do + if test -d $BUILD/$bind ; then + . $BUILD/$bind/bind.conf + else + . $BUILD/bin/$bind.bind + fi + done +fi + +# +# Parse command line arguments. +# +err='' + +if test ! -z "$CONFIG_FLAGS" ; then + for arg in $CONFIG_FLAGS ; do + for opt in $BIND_OPTS ; do + case "$arg" in + $opt=* | -$opt=* | --$opt=* ) + opt_$opt `echo "$arg" | sed 's/[-_a-zA-Z0-9]*=//'` + break + ;; + esac + done + done +fi + + +if test ! -z "$*" ; then + for arg in $* ; do + err=$arg + for opt in $BIND_OPTS ; do + case "$arg" in + $opt=* | -$opt=* | --$opt=* ) + opt_$opt `echo "$arg" | sed 's/[-_a-zA-Z0-9]*=//'` + err='' + break + ;; + esac + done + if test ! -z "$err" ; then + break + fi + done +fi + +CONFIG_FLAGS='' + +if test ! -z "$err" ; then + echo "config: $err: invalid option." + echo + echo "Valid Options:" + echo -n >config.help + if test ! -z "$BIND" ; then + for use in $BIND ; do + if test -f $BUILD/$use/help.conf ; then + cat $BUILD/$use/help.conf >>config.help + fi + if test -f $BUILD/bin/$use.help ; then + cat $BUILD/bin/$use.help >>config.help + fi + done + sort <config.help + rm -f config.help + fi + exit -1 +fi + +echo "#ifndef __CONFIG_H__" >>$CONFIG +echo "#define __CONFIG_H__" >>$CONFIG + +CONFIG_LIBS="" + +if test ! -z "$BIND" ; then + for bind in $BIND ; do + if test -d $BUILD/$bind ; then + . $BUILD/$bind/make.conf + CONFIG_LIBS='-l'$bind' '"$CONFIG_LIBS" + MAKEFILES="$MAKEFILES"' '$BUILD/$bind/Makefile + else + . $BUILD/bin/$bind.make + fi + done +fi + +if test ! -z "$CONFIG_LIBS" ; then + echo "LIBS=$CONFIG_LIBS" >>config.make +fi + +if test ! -z "$MAKEFILES" ; then + for makefile in $MAKEFILES ; do + cat config.make >$makefile + cat $makefile.in >>$makefile + done +fi + +echo "#endif" >>$CONFIG + + +if test -z "$CONFIG_CACHE" ; then + CONFIG_CACHE='config.cache' + CONFIG_FLAGS='' +else + CONFIG_FIRST='' +fi + +echo "CONFIG_CACHE="$CONFIG_CACHE >>config.cache + +if test -f conftest.c ; then + rm -f conftest.c +fi + +if test -f conftest.o ; then + rm conftest.o +fi + +if test ! -z "$CONFIG_FIRST" ; then + $CONFIG_FIRST +fi + diff --git a/config.diag b/config.diag new file mode 100644 index 0000000..15a36f3 --- /dev/null +++ b/config.diag @@ -0,0 +1,5 @@ +# Gather startup services info + +startup='yes' +files='/etc/rc.d/rc.serial' + diff --git a/config.dist b/config.dist new file mode 100644 index 0000000..2ec39c8 --- /dev/null +++ b/config.dist @@ -0,0 +1,12 @@ +version="1.0" +package="speak" +examine="utils sdk spo256 spktrapd html" +config="config.pkg config.dist config.diag config sdk/bin/*" +include="Makefile.in README.FIRST CHANGES TODO LICENSE speak.lsm" + +manpages="down.8 say.1 speak.1 speak.conf.7 spo256.8 vmon.8" +txtpages="CHANGES LICENSE README.FIRST TARGETS TODO" +lsmpages="speak.lsm" +htmlpages="index.html toc.html" +htmlhome=packages/speak + diff --git a/config.pkg b/config.pkg new file mode 100644 index 0000000..9c7aa53 --- /dev/null +++ b/config.pkg @@ -0,0 +1,9 @@ +# +# Denote package bindings +# +BIND='install std proc other net dev' +MAKEFILES='Makefile spo256/Makefile utils/Makefile' +CONFIG_FLAGS=$CONFIG_FLAGS +CONFIG_FIRST='make' +CONFIG_INSTALL='make install' + diff --git a/html/README b/html/README new file mode 100644 index 0000000..5a4f414 --- /dev/null +++ b/html/README @@ -0,0 +1,4 @@ +This directory holds html templates used as part of make 'web' when +building a html redistribution directory. Otherwise, this directory may +be ignored. + diff --git a/html/index.html b/html/index.html new file mode 100644 index 0000000..ad54365 --- /dev/null +++ b/html/index.html @@ -0,0 +1,10 @@ +<html> +<head> +<title>UNIX Speak Server 0.2pl2</title> +</head> + +<frameset COLS="27%,73%"> +<frame SRC="toc.html" NAME="contents"> +<frame SRC="speak.lsm.html" NAME="main"> +</frameset> +</html> diff --git a/html/toc.html b/html/toc.html new file mode 100755 index 0000000..429ec78 --- /dev/null +++ b/html/toc.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> + +<html> + +<head> +<title>TOC</title> +<meta name="GENERATOR" content="Microsoft FrontPage 1.1"> +<base target="main"> +</head> + +<body> +<p><font size=4><em><strong>General</strong></em></font></p> +<dir> +<li><a href="speak.lsm.html" target="main"><em>About</em></a></li> +<li><a href="CHANGES.txt" target="main"><em>Changes</em></a></li> +<li><a href="ftp://ftp.tycho.com/dist/speak-1.0.tar.gz" target="main"><em>Download</em></a></li> +<li><a href="mailto:dyfet@tycho.com" target="main"><em>Feedback</em></a></li> +<li><a href="LICENSE.txt" target="main"><em>License</em></a></li> +<li><a href="README.FIRST.txt" target="main"><em>Readme</em></a></li> +<li><a href="TARGETS.txt" target="main"><em>Targets</em></a></li> +<li><a href="TODO.txt" target="main"><em>Todo</em></a></li> +</dir> +<p><font size=4><em><strong>Manpages</strong></em></font></p> +<dir> +<li><a href="down.html" target="main"><em>down.8</em></a></li> +<li><a href="say.html" target="main"><em>say.1</em></a></li> +<li><a href="speak.html" target="main"><em>speak.1</em></a></li> +<li><a href="speak.conf.html" target="main"><em>speak.conf.7</em></a></li> +<li><a href="spo256.html" target="main"><em>spo256.8</em></a></li> +<li><a href="vmon.html" target="main"><em>vmon.8</em></a></li> +</dir> +<p> </p> +</body> + +</html> diff --git a/sdk/bin/clean b/sdk/bin/clean new file mode 100755 index 0000000..2667461 --- /dev/null +++ b/sdk/bin/clean @@ -0,0 +1,22 @@ +#!/bin/sh +flist=`find . -name core -follow -print` +if [ ! -z "$flist" ] ; then + rm $flist +fi + +flist=`find . -name "*~" -follow -print` +if [ ! -z "$flist" ] ; then + rm $flist +fi + +flist=`find . -name "*.tar.gz" -follow -print` +if [ ! -z "$flist" ] ; then + rm $flist +fi + +flist=`find . -name "config.c*" -follow -print` +if [ ! -z "$flist" ] ; then + rm $flist +fi + + diff --git a/sdk/bin/config b/sdk/bin/config new file mode 100755 index 0000000..a701bc8 --- /dev/null +++ b/sdk/bin/config @@ -0,0 +1,175 @@ +#!/bin/sh + +# +# Reload defaults +# + +BUILD=sdk +CONFIG=sdk/config.h + +if test -f config.cache ; then + . ./config.cache +fi +echo -n >config.cache + +if test -f config.pkg ; then + . ./config.pkg +fi + +# +# Load bindings +# + +if test -f config.pkg ; then + . ./config.pkg +fi + +if test -f config.make ; then + echo -n >config.make +fi + +if test -f $CONFIG ; then + echo -n >$CONFIG +fi + +if test -f $BUILD/bin/config.sub ; then + . $BUILD/bin/config.sub +fi + +BIND_OPTS='host' + +if test -z "$CONFIG_HOST" ; then + if test -d /usr/local/include ; then + CONFIG_HOST=/usr/local + fi + if test -d /usr/include ; then + CONFIG_HOST=/usr + fi +fi + +opt_host() { + CONFIG_HOST="$1" + return 0 +} + +if test ! -z "$BIND" ; then + for bind in $BIND ; do + if test -d $BUILD/$bind ; then + . $BUILD/$bind/bind.conf + else + . $BUILD/bin/$bind.bind + fi + done +fi + +# +# Parse command line arguments. +# +err='' + +if test ! -z "$CONFIG_FLAGS" ; then + for arg in $CONFIG_FLAGS ; do + for opt in $BIND_OPTS ; do + case "$arg" in + $opt=* | -$opt=* | --$opt=* ) + opt_$opt `echo "$arg" | sed 's/[-_a-zA-Z0-9]*=//'` + break + ;; + esac + done + done +fi + + +if test ! -z "$*" ; then + for arg in $* ; do + err=$arg + for opt in $BIND_OPTS ; do + case "$arg" in + $opt=* | -$opt=* | --$opt=* ) + opt_$opt `echo "$arg" | sed 's/[-_a-zA-Z0-9]*=//'` + err='' + break + ;; + esac + done + if test ! -z "$err" ; then + break + fi + done +fi + +CONFIG_FLAGS='' + +if test ! -z "$err" ; then + echo "config: $err: invalid option." + echo + echo "Valid Options:" + echo -n >config.help + if test ! -z "$BIND" ; then + for use in $BIND ; do + if test -f $BUILD/$use/help.conf ; then + cat $BUILD/$use/help.conf >>config.help + fi + if test -f $BUILD/bin/$use.help ; then + cat $BUILD/bin/$use.help >>config.help + fi + done + sort <config.help + rm -f config.help + fi + exit -1 +fi + +echo "#ifndef __CONFIG_H__" >>$CONFIG +echo "#define __CONFIG_H__" >>$CONFIG + +CONFIG_LIBS="" + +if test ! -z "$BIND" ; then + for bind in $BIND ; do + if test -d $BUILD/$bind ; then + . $BUILD/$bind/make.conf + CONFIG_LIBS='-l'$bind' '"$CONFIG_LIBS" + MAKEFILES="$MAKEFILES"' '$BUILD/$bind/Makefile + else + . $BUILD/bin/$bind.make + fi + done +fi + +if test ! -z "$CONFIG_LIBS" ; then + echo "LIBS=$CONFIG_LIBS" >>config.make +fi + +if test ! -z "$MAKEFILES" ; then + for makefile in $MAKEFILES ; do + cat config.make >$makefile + cat $makefile.in >>$makefile + done +fi + +echo "#endif" >>$CONFIG + + +if test -z "$CONFIG_CACHE" ; then + CONFIG_CACHE='config.cache' + CONFIG_FLAGS='' +else + CONFIG_FIRST='' +fi + +echo "CONFIG_CACHE="$CONFIG_CACHE >>config.cache + +if test -f conftest.c ; then + rm -f conftest.c +fi + +if test -f conftest.o ; then + rm conftest.o +fi + +if test ! -z "$CONFIG_FIRST" ; then + $CONFIG_FIRST +fi + diff --git a/sdk/bin/config.sub b/sdk/bin/config.sub new file mode 100755 index 0000000..81a7488 --- /dev/null +++ b/sdk/bin/config.sub @@ -0,0 +1,38 @@ +fn_find_fpath() { + save_ifs="$IFS" + IFS="${IFS}:" + for dir in $3 ; do + if test $1 $dir/$2 ; then + IFS="$save_ifs" + return 0 + fi + done + IFS="$save_ifs" + return 1 +} + +fn_find_type() { + fail=$1 + shift + text=$1 + shift + for fn in $* ; do + if test -f "$fn" ; then + grep "$text" <$fn >/dev/null + if test ! $? = 1 ; then + return 1 + fi + fi + done + echo "#define "$fail >>$CONFIG + return 0 +} + +fn_find_file() { + if test ! -f $2 ; then + echo "#define "$1 >>$CONFIG + return 1 + fi + return 0 +} + diff --git a/sdk/bin/diag b/sdk/bin/diag new file mode 100755 index 0000000..aa56844 --- /dev/null +++ b/sdk/bin/diag @@ -0,0 +1,171 @@ +#!/bin/sh + +files='' +ldd='no' +gcc='no' +hardware='no' +startup='no' +drivers='no' +symbols='no' +tracer='' + +if [ -f /usr/bin/strace ] ; then + tracer='strace' +fi + +if [ -f /bin/strace ] ; then + tracer='strace' +fi + +if [ -f /sbin/strace ] ; then + tracer='strace' +fi + +if [ -f /bin/ldd ] ; then + ldd='yes' +fi + +if [ -f /usr/bin/ldd ] ; then + ldd='yes' +fi + +if [ -f /usr/bin/gcc ] ; then + gcc='yes' +fi + +if [ -f /usr/local/bin/gcc ] ; then + gcc='yes' +fi + +if [ -f config.diag ] ; then + . ./config.diag +fi + +if [ ! -z "$title" ] ; then + echo $title +fi + +if [ ! -z "$strace" ] ; then + for trace in $strace ; do + echo + ls -l $trace + if [ $ldd = 'yes' ] ; then + echo + echo "Library map for " $trace + ldd $trace + fi + if [ $symbols = 'yes' ] ; then + echo + nm $trace + fi + if [ ! -z "$tracer" ] ; then + echo + $tracer $opts $trace 2>&1 + fi + done +fi + +echo +echo -n "System Type: " +uname -s + +echo -n "Achitecture: " +uname -m + +echo -n "Release: " +uname -r + +if [ $gcc = 'yes' ] ; then + echo + echo "GCC Information:" + gcc -v 2>&1 +fi + +if [ -f /proc/meminfo ] ; then + echo + echo "Memory:" + cat /proc/meminfo +fi + +echo "" +echo "Disks:" +df + +if [ $startup = 'yes' ] ; then + + if [ -d /etc/rc.d ] ; then + echo + echo "Services:" + ls -l /etc/rc.d + if [ -d /etc/rc.d/rc3.d ] ; then + echo + echo "Startup:" + ls /etc/rc.d/rc3.d + fi + fi +fi + +if [ -f config.cache ] ; then + echo + echo "Configuration:" + cat config.cache +fi + +if [ -f config.cc ] ; then + echo + echo "Compiler:" + cat config.cc +fi + +if [ ! -z "$files" ] ; then + for file in $files ; do + if [ -f $file ] ; then + echo + echo "Found: " $file + echo + cat $file + fi + done +fi + +if [ $drivers = 'yes' ] ; then + + if [ -f /proc/modules ] ; then + echo + echo "Modules:" + cat /proc/modules + fi +fi + +if [ $hardware = 'yes' ] ; then + + if [ -f /proc/devices ] ; then + echo + echo "Devices:" + cat /proc/devices + fi + + if [ -f /proc/ioports ] ; then + echo + echo "Ports:" + cat /proc/ioports + fi + + if [ -f /proc/interrupts ] ; then + echo + echo "Interrupts:" + cat /proc/interrupts + fi + + if [ -f /proc/dma ] ; then + echo + echo "DMA:" + cat /proc/dma + fi + + if [ -f /proc/cpuinfo ] ; then + echo + cat /proc/cpuinfo + fi +fi + diff --git a/sdk/bin/dist b/sdk/bin/dist new file mode 100755 index 0000000..43c6ef9 --- /dev/null +++ b/sdk/bin/dist @@ -0,0 +1,63 @@ +#!/bin/sh + +if test ! -f config.dist ; then + echo "dist: config.dist missing!" +fi + +# defaults! + +distdir=$1 +config="config.dist config.pkg build" +exclude="*.o *.a config.cc config.cache config *.tar.gz *~ core Makefile" +exclude_exe="true" +exclude_files=".EXCLUDE" + +. ./config.dist + +root=`pwd` +dist=$package'-'$version +cd .. + +if test ! $dist = $root ; then + rm -f $dist + ln -s $root $dist +fi + +xlist=$dist/.EXCLUDE +echo -n >$xlist +for file in $exclude_files ; do + echo $dist/$file >>$xlist +done + +flist="" + +for cfg in $include $config ; do + flist=$flist' '$dist/$cfg +done + +for dir in $examine ; do + flist=$flist' '$dist/$dir + if test $exclude_exe = "true" ; then + find $dist/$dir -perm +1 -type f -follow -print >>$xlist + fi + for deny in $exclude ; do + find $dist/$dir -follow -name $deny -print >>$xlist + done +done + +target=$dist/$dist.tar.gz +if test -d $distdir ; then + rm -f $distdir/${package}*.tar.gz + target=$distdir/$dist.tar.gz + if test -f $dist/$package'.lsm' ; then + cp -f $dist/$package'.lsm' $distdir + fi +fi + +tar -X $xlist -cvhzf $target $flist + +if [ ! $dist = $root ] ; then + rm $dist +fi + + diff --git a/sdk/bin/disthtml b/sdk/bin/disthtml new file mode 100755 index 0000000..4caa151 --- /dev/null +++ b/sdk/bin/disthtml @@ -0,0 +1,31 @@ +#!/bin/sh + +manprefix=$2 + +if test -f config.dist ; then + . ./config.dist +fi + +if test -z $htmlhome ; then + htmlhome=$1/$package +else + htmlhome=$1/$htmlhome +fi + +man2html $manprefix $manpages $htmlhome + +for lsmpage in $lsmpages ; do + echo "Creating $lsmpage.html..." + lsm2html $lsmpage >$htmlhome/$lsmpage.html +done + +for txtpage in $txtpages ; do + echo "Creating $txtpage.txt" + cp $txtpage $htmlhome/$txtpage.txt +done + +for htmlpage in $htmlpages ; do + echo "Copying $htmlpage" + cp -f html/$htmlpage $htmlhome/$htmlpage +done + diff --git a/sdk/bin/install.bind b/sdk/bin/install.bind new file mode 100755 index 0000000..1a00236 --- /dev/null +++ b/sdk/bin/install.bind @@ -0,0 +1,55 @@ +BIND_OPTS=$BIND_OPTS' prefix eprefix share bindir sbindir confdir mandir infodir libdir slibdir root htmldir distdir' + +opt_prefix() { + CONFIG_PREFIX="$1" +} + +opt_eprefix() { + CONFIG_EPREFIX="$1" +} + +opt_share() { + CONFIG_SHARE="$1" +} + +opt_bindir() { + CONFIG_BINDIR="$1" +} + +opt_sbindir() { + CONFIG_SBINDIR="$1" +} + +opt_confdir() { + CONFIG_CONFDIR="$1" +} + +opt_root() { + CONFIG_ROOT="$1" +} + +opt_libdir() { + CONFIG_LIBDIR="$1" +} + +opt_slibdir() { + CONFIG_SLIBDIR="$1" +} + +opt_mandir() { + CONFIG_MANDIR="$1" +} + +opt_infodir() { + CONFIG_INFODIR="$1" +} + +opt_htmldir() { + CONFIG_HTMLDIR="$1" +} + +opt_distdir() { + CONFIG_DISTDIR="$1" +} + + diff --git a/sdk/bin/install.help b/sdk/bin/install.help new file mode 100755 index 0000000..6907439 --- /dev/null +++ b/sdk/bin/install.help @@ -0,0 +1,12 @@ +--root= Installation root offset (NONE) +--prefix= Default installation prefix (/usr) +--eprefix= Execution installation prefix (/usr) +--bindir= Bin directory ($exec-prefix/bin) +--sbindir= System bin directory ($exec-prefix/sbin) +--libdir= Library directory ($exec-prefix/lib) +--slibdir= System library directory ($exec-prefix/lib) +--confdir= Config file directory (/etc) +--share= Shared data directory ($prefix/share) +--mandir= Manual directory ($share/man) +--infodir= Info file directory ($share/info) +--htmldir= HTML Documentation ($share/html) diff --git a/sdk/bin/install.make b/sdk/bin/install.make new file mode 100755 index 0000000..fc63cc6 --- /dev/null +++ b/sdk/bin/install.make @@ -0,0 +1,112 @@ +echo "root="$CONFIG_ROOT >>config.make + +if test -z "$CONFIG_PREFIX" ; then + echo 'prefix=$(root)'$CONFIG_HOST >>config.make +else + echo 'prefix=$(root)'$CONFIG_PREFIX >>config.make +fi + +if test -z "$CONFIG_EPREFIX" ; then + echo 'eprefix=$(prefix)' >>config.make +else + echo 'eprefix=$(root)'$CONFIG_EPREFIX >>config.make +fi + +if test -z "$CONFIG_SHARE" ; then + if test -d $CONFIG_HOST/share ; then + echo 'share=$(prefix)/share' >>config.make + else + echo 'share=$(prefix)' >>config.make + fi +else + echo 'share=$(root)'$CONFIG_SHARE >>config.make +fi + + +if test -z "$CONFIG_CONFDIR" ; then + echo 'SYSCONFDIR=$(root)/etc' >>config.make +else + echo 'SYSCONFDIR=$(root)'$CONFIG_CONFDIR >>config.make +fi + +if test -z "$CONFIG_BINDIR" ; then + echo 'BINDIR=$(eprefix)/bin' >>config.make +else + echo 'BINDIR=$(root)'$CONFIG_BINDIR >>config.make +fi + +if test -z "$CONFIG_SBINDIR" ; then + if test -d $CONFIG_HOST/sbin ; then + echo 'SBINDIR=$(eprefix)/sbin' >>config.make + else + echo 'SBINDIR=$(root)/etc' >>config.make + fi +else + echo 'SBINDIR=$(root)'$CONFIG_SBINDIR >>config.make +fi + +if test -z "$CONFIG_LIBDIR" ; then + echo 'LIBDIR=$(eprefix)/lib' >>config.make +else + echo 'LIBDIR=$(root)'$CONFIG_LIBDIR >>config.make +fi + +if test -z "$CONFIG_SLIBDIR" ; then + echo 'SLIBDIR=$(root)/lib' >>config.make +else + echo 'SLIBDIR=$(root)'$CONFIG_SLIBDIR >>config.make +fi + +if test -z "$CONFIG_MANDIR" ; then + if test -d $CONFIG_HOST/share/man ; then + echo 'MANDIR=$(share)/man' >>config.make + else + echo 'MANDIR=$(prefix)/man' >>config.make + fi +else + echo 'MANDIR=$(root)'$CONFIG_MANDIR >>config.make +fi + +if test -z "$CONFIG_INFODIR" ; then + if test -d $CONFIG_HOST/share/info ; then + echo 'INFODIR=$(share)/info' >>config.make + else + echo 'INFODIR=$(prefix)/info' >>config.make + fi +else + echo 'INFODIR=$(root)'$CONFIG_INFODIR >>config.make +fi + +if test -z "$CONFIG_HTMLDIR" ; then + if test -d $CONFIG_HOST/share/html ; then + echo 'HTMLDIR=$(share)/html' >>config.make + else + echo 'HTMLDIR=$(prefix)/html' >>config.make + fi +else + echo 'HTMLDIR=$(root)'$CONFIG_HTMLDIR >>config.make +fi + +if test -z "$CONFIG_DISTDIR" ; then + if test -d $CONFIG_HOST/share/dist ; then + echo 'DISTDIR=$(share)/dist' >>config.make + else + echo 'DISTDIR=$(prefix)/dist' >>config.make + fi +else + echo 'DISTDIR=$(root)'$CONFIG_DISTDIR >>config.make +fi + +echo "CONFIG_ROOT="$CONFIG_ROOT >>config.cache +echo "CONFIG_PREFIX="$CONFIG_PREFIX >>config.cache +echo "CONFIG_EPREFIX="$CONFIG_EPREFIX >>config.cache +echo "CONFIG_SHARE="$CONFIG_SHARE >>config.cache +echo "CONFIG_CONFDIR="$CONFIG_CONFDIR >>config.cache +echo "CONFIG_BINDIR="$CONFIG_BINDIR >>config.cache +echo "CONFIG_SBINDIR="$CONFIG_SBINDIR >>config.cache +echo "CONFIG_LIBDIR="$CONFIG_LIBDIR >>config.cache +echo "CONFIG_SLIBDIR="$CONFIG_SLIBDIR >>config.cache +echo "CONFIG_INFODIR="$CONFIG_INFODIR >>config.cache +echo "CONFIG_MANDIR="$CONFIG_MANDIR >>config.cache +echo "CONFIG_HTMLDIR="$CONFIG_HTMLDIR >>config.cache +echo "CONFIG_DISTDIR="$CONFIG_DISTDIR >>config.cache diff --git a/sdk/bin/instinit b/sdk/bin/instinit new file mode 100755 index 0000000..fdd0899 --- /dev/null +++ b/sdk/bin/instinit @@ -0,0 +1,61 @@ +#!/bin/sh +run=/etc/rc.d +levels="" +base=$1 + +if [ ! -d $run ] ; then + exit 0 +fi + +if [ -d $run/init.d ] ; then + levels=$run + init='../init.d/'$1'.init' + run=$run/init.d + target=$1'.init' +else + target='rc.'$1 + levels='false' +fi + +source=$1'.init' +shift + +if [ ! -f "$run/$target" ] ; then + echo 'Adding '$target' to '$run + if [ -f /etc/sudo.conf ] ; then + sudo root install -o root -m 0700 $source $run/$target + else + su root -c "install -o root -m 0700 $source $run/$target" + fi +else + exit 0 +fi + +if [ -z "$BASH" ] ; then + exit 0 +fi + +if [ -z "$levels" ] ; then + exit 0 +fi + +initial=$1 +shift + +for level in $* ; do + runlvl=$levels'/rc'$level'.d' + if [ ! -d $runlvl ] ; then + continue + fi + cd $runlvl + count=$initial + while [ -f *$count* ] ; do + count=$[count + 1] + done + target='S'$count$base + echo 'Adding '$target' to '$runlvl + ln -s $init $target +done + + + diff --git a/sdk/bin/instman b/sdk/bin/instman new file mode 100755 index 0000000..d8ca6f7 --- /dev/null +++ b/sdk/bin/instman @@ -0,0 +1,32 @@ +#!/bin/sh +prefix=$1 +set=$2 +shift +shift + +for page in $* ; do + source=$page'.'$set + target="" + if [ -d $prefix/man$set ] ; then + mandir=$prefix/man$set + target=$mandir/$page'.'$set + fi + if [ -z $target ] ; then + roff=nroff + if [ -f /usr/lib/groff ] ; then + roff="groff -Tascii" + fi + if [ -f /usr/local/lib/groff ] ; then + roff="groff -Tascii" + fi + if [ -d $prefix/cat$set ] ; then + mandir=$prefix/cat$set + target=$mandir/$page.set + $roff -man <$source >$page'.man' + source=$page'.man' + fi + fi + echo 'Adding '$page' to '$mandir + install -g man -m 0664 $source $target +done + diff --git a/sdk/bin/instso b/sdk/bin/instso new file mode 100755 index 0000000..148a82a --- /dev/null +++ b/sdk/bin/instso @@ -0,0 +1,39 @@ +#!/bin/sh + +prefix=$1 +libname=$2 +version=$3 + +# find project root. + +root=`dirname $0` +root=`dirname $root` + +# fetch package 'version' level from project root (config.dist). + +if [ -f $root/config.dist ] ; then + . $root/config.dist +fi + +if [ ! -d $(prefix)/lib ] ; then + prefix=$/usr + if [ ! -d /usr/lib ] ; then + exit 0 + fi +fi + +prefix=$prefix/lib +echo 'Installing '$libname'.so to '$prefix +cp -f $libname'.so' $(prefix)/$(libname)'.so.'$version +ldconfig -n $(prefix) + +liblist=`find $(prefix) -name "$(libname).so.*" -type f -print` +for lib in $liblist ; do + if [ ! $lib = $libname'.so.'$version ] ; then + rm $lib + fi +done + +ldconfig -n $(prefix) + + diff --git a/sdk/bin/instsvc b/sdk/bin/instsvc new file mode 100755 index 0000000..468fe2a --- /dev/null +++ b/sdk/bin/instsvc @@ -0,0 +1,27 @@ +#!/bin/sh + +etc='/etc' + +if [ ! -d "$etc" ] ; then + etc='' + if [ -d /config ] ; then + etc='/config' + fi +fi + +if [ -z "$etc" ] ; then + exit 0 +fi + +svc=$etc/$1 +shift +base=$1 +shift +line=$base" $*" + +grep "^$base" <$svc >/dev/null +if [ $? = 1 ] ; then + echo "Adding $base to $svc" + echo $line >>$svc +fi + diff --git a/sdk/bin/rootsudo b/sdk/bin/rootsudo new file mode 100755 index 0000000..3ff65f1 --- /dev/null +++ b/sdk/bin/rootsudo @@ -0,0 +1,6 @@ +#!/bin/sh +if [ -f /etc/sudo.conf ] ; then + sudo root $* +else + su root -c "$*" +fi diff --git a/sdk/config.h b/sdk/config.h new file mode 100644 index 0000000..6af2aa5 --- /dev/null +++ b/sdk/config.h @@ -0,0 +1,16 @@ +#ifndef __CONFIG_H__ +#define __CONFIG_H__ +#define EMPTY 0 +#define UCHAR_T_MISSING +#define FD_T_MISSING +#define STRLWR_F_MISSING +#define STRISTR_F_MISSING +#define PROCESS_H_MISSING +#define SYS_SELECT_H_MISSING +#define SELECT_H_MISSING +#define POLL_H_MISSING +#define SYS_POLL_H_MISSING +#define SYSCONF_H_MISSING +#define ENV_H_MISSING +#define IO_H_MISSING +#endif diff --git a/sdk/dev/Makefile.in b/sdk/dev/Makefile.in new file mode 100644 index 0000000..1375154 --- /dev/null +++ b/sdk/dev/Makefile.in @@ -0,0 +1,19 @@ +# +# Template to build device interface library. +# $Id$ +# Copyright (c) 1997 by Tycho Softworks. +# + +OBJS = inkey.o empty.o input.o waitfor.o waitsync.o xmit.o \ + speed.o format.o flowctrl.o interactive.o stty.o + +.c.o: + $(CC) $(CFLAGS) $(OPTIMIZE) -I.. -o $@ -c $< + $(AR) r ../lib/libdev.a $@ + +all: $(OBJS) + ranlib ../lib/libdev.a + +clean: + rm *.o + diff --git a/sdk/dev/bind.conf b/sdk/dev/bind.conf new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sdk/dev/bind.conf diff --git a/sdk/dev/empty.c b/sdk/dev/empty.c new file mode 100644 index 0000000..87114a3 --- /dev/null +++ b/sdk/dev/empty.c @@ -0,0 +1,15 @@ +/* + * Empty the serial input fifo buffer. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <dev/tty.h> + +void empty(int fd) +{ + while(inkey(fd, 0) > -1) + continue; +} + diff --git a/sdk/dev/flowctrl.c b/sdk/dev/flowctrl.c new file mode 100644 index 0000000..7977b1c --- /dev/null +++ b/sdk/dev/flowctrl.c @@ -0,0 +1,47 @@ +/* + * Serial line flow control option settings. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <dev/tty.h> +#ifndef TERMIOS_H_MISSING +#include <termios.h> +#endif + +#ifndef CRTSCTS +#ifdef CTSFLOW +#define CRTSCTS CTSFLOW | CRTSFL +#endif +#endif + +int setflowctrl(stty_t stty, FLOWCONTROL flow) +{ +#ifndef TERMIOS_H_MISSING + + struct termios *tios = stty; + tios->c_cflag &= ~CRTSCTS; + tios->c_iflag &= ~(IXON | IXOFF | IXANY); + + switch(flow) + { + case FC_HARD: + tios->c_cflag |= CRTSCTS; + break; + case FC_SOFT: + tios->c_iflag |= (IXON | IXOFF | IXANY); + break; + case FC_FULL: + tios->c_cflag |= CRTSCTS; + tios->c_iflag |= (IXON | IXOFF | IXANY); + break; + } +#endif + return 0; +} + + + + + diff --git a/sdk/dev/format.c b/sdk/dev/format.c new file mode 100644 index 0000000..508ec6c --- /dev/null +++ b/sdk/dev/format.c @@ -0,0 +1,64 @@ +/* + * Specify serial port data line format. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <dev/tty.h> +#ifndef TERMIOS_H_MISSING +#include <termios.h> +#endif + +int setformat(stty_t stty, char *format) +{ +#ifndef TERMIOS_H_MISSING + struct termios *tios = stty; + + tios->c_cflag &= ~CSIZE; + if(format[2] == '1') + tios->c_cflag &= ~CSTOPB; + else + tios->c_cflag |= CSTOPB; + + switch(format[0]) + { + case '5': + tios->c_cflag |= CS5; + break; + case '6': + tios->c_cflag |= CS6; + break; + case '7': + tios->c_cflag |= CS7; + break; + case '8': + tios->c_cflag |= CS8; + break; + } + + switch(format[1]) + { + case 'n': + case 'N': + tios->c_cflag &= ~(PARODD | PARENB); + break; + case 'e': + case 'E': + tios->c_cflag |= PARENB; + tios->c_cflag &= ~PARODD; + break; + case 'o': + case 'O': + tios->c_cflag |= (PARENB | PARODD); + break; + } + +#endif + return 0; +} + + + + + diff --git a/sdk/dev/inkey.c b/sdk/dev/inkey.c new file mode 100644 index 0000000..1003905 --- /dev/null +++ b/sdk/dev/inkey.c @@ -0,0 +1,76 @@ +/* + * Wait and read single byte input from device. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <dev/tty.h> +#include <std/select.h> +#include <std/poll.h> + +#ifndef SYS_POLL_H_MISSING +#define USE_POLL +#endif + +#ifndef POLL_H_MISSING +#define USE_POLL +#endif + +#ifdef USE_POLL + +int inkey(fd_t fd, int timeout) +{ + struct pollfd poller; + uchar buf; + + poller.fd = fd; + poller.revents = 0; + poller.events = POLLIN ; + + if(!poll(&poller, 1, timeout)) + return -1; + + if(poller.revents & (POLLERR | POLLHUP)) + return -1; + + if(read(fd, &buf, 1) != 1) + return -1; + + return buf; +} + +#else + +int inkey(fd_t fd, int timeout) +{ + fd_set inp,out,exc; + struct timeval timer; + uchar buf; + + FD_ZERO(&inp); + FD_ZERO(&out); + FD_ZERO(&exc); + + FD_SET(fd, &inp); + FD_SET(fd, &exc); + + timer.tv_sec = timeout / 1000; + timer.tv_usec = timeout % 1000; + + if(!select(fd + 1, &inp, &out, &exc, &timer)) + return -1; + + if(FD_ISSET(fd, &exc)) + return -1; + + if(FD_ISSET(fd, &inp)) + { + if(read(fd, &buf, 1) != 1) + return -1; + return buf; + } + return -1; +} + +#endif diff --git a/sdk/dev/input.c b/sdk/dev/input.c new file mode 100644 index 0000000..95494d3 --- /dev/null +++ b/sdk/dev/input.c @@ -0,0 +1,34 @@ +/* + * Read a line of input from device. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <std/string.h> +#include <dev/tty.h> + +int input(int fd, uchar *buf, size_t len, int timeout, const uchar *term) +{ + int key; + int idx = 0; + + while(idx < len) + { + key = inkey(fd, timeout); + if(key < 0) + return idx; + + if(!key) + continue; + + buf[idx++] = (uchar)(key & 0xff); + if(strchr((char *)term, key)) + break; + } + buf[idx] = 0; + return idx; +} + + + diff --git a/sdk/dev/interactive.c b/sdk/dev/interactive.c new file mode 100644 index 0000000..be998e6 --- /dev/null +++ b/sdk/dev/interactive.c @@ -0,0 +1,35 @@ +/* + * Select raw or "interactive" terminal mode for device. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <dev/tty.h> +#ifndef TERMIOS_H_MISSING +#include <termios.h> +#endif + +bool interactive(stty_t stty, bool mode) +{ +#ifndef TERMIOS_H_MISSING + + struct termios *tios = stty; + + if(mode) + { + + } + else + { + tios->c_oflag = 0; + tios->c_lflag = 0; + } +#endif + return mode; +} + + + + + diff --git a/sdk/dev/make.conf b/sdk/dev/make.conf new file mode 100644 index 0000000..8a396ea --- /dev/null +++ b/sdk/dev/make.conf @@ -0,0 +1,5 @@ +inc=$CONFIG_HOST/include +fn_find_file TERMIOS_H_MISSING $inc/termios.h +fn_find_file TERMIO_H_MISSING $inc/termio.h +fn_find_file TERMCAP_H_MISSING $inc/termcap.h + diff --git a/sdk/dev/speed.c b/sdk/dev/speed.c new file mode 100644 index 0000000..f9fee56 --- /dev/null +++ b/sdk/dev/speed.c @@ -0,0 +1,75 @@ +/* + * Specify serial communications speed. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <dev/tty.h> +#ifndef TERMIOS_H_MISSING +#include <termios.h> +#endif + +int setspeed(stty_t tios, ulong speed) +{ + +#ifdef B38400 + int rate = B38400; +#else + int rate = B19200; +#endif + + switch(speed) + { + case 110: + rate = B110; + break; + case 300: + rate = B300; + break; + case 600: + rate = B600; + break; + case 1200: + rate = B1200; + break; + case 2400: + rate = B2400; + break; + case 4800: + rate = B4800; + break; + case 9600: + rate = B9600; + break; + case 19200: + rate = B19200; + break; +#ifdef B38400 + case 38400: + rate = B38400; + break; +#endif +#ifdef B57600 + case 57600: + rate = B57600; + break; +#endif +#ifdef B115200 + case 115200: + rate = B115200; + break; +#endif + } + +#ifndef TERMIOS_H_MISSING + cfsetospeed(tios, rate); + cfsetispeed(tios, rate); +#endif + return rate; +} + + + + + diff --git a/sdk/dev/stty.c b/sdk/dev/stty.c new file mode 100644 index 0000000..9a465da --- /dev/null +++ b/sdk/dev/stty.c @@ -0,0 +1,29 @@ +/* + * Portable routines to get and set serial device attributes. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <dev/tty.h> + +#ifndef TERMIOS_H_MISSING +#include <termios.h> + +stty_t getstty(fd_t fd) +{ + stty_t stty = (stty_t)malloc(sizeof(struct termios)); + tcgetattr(fd, stty); + return stty; +} + +void putstty(fd_t fd, stty_t stty, bool now) +{ + if(now) + tcsetattr(fd, TCSANOW, stty); + else + tcsetattr(fd, TCSADRAIN, stty); + free(stty); +} +#endif + diff --git a/sdk/dev/termcap.h b/sdk/dev/termcap.h new file mode 100644 index 0000000..e2cbb5b --- /dev/null +++ b/sdk/dev/termcap.h @@ -0,0 +1,17 @@ +/* + * Portable termcap header. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions on distribution and reuse see product license. + */ + +#ifndef __DEV_TERMCAP_H__ +#define __DEV_TERMCAP_H__ + +#ifndef TERMCAP_H_MISSING +#include <termcap.h> +#else +#endif + +#endif + diff --git a/sdk/dev/tty.h b/sdk/dev/tty.h new file mode 100644 index 0000000..3ff02ca --- /dev/null +++ b/sdk/dev/tty.h @@ -0,0 +1,72 @@ +/* + * Portable serial interface control and operation. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __DEV_TTY_H__ +#define __DEV_TTY_H__ + +#ifndef __STD_TYPES_H__ +#include <std/types.h> +#endif + +#ifndef __STD_FILES_H__ +#include <std/files.h> +#endif + +typedef void *stty_t; + +#ifdef __cplusplus +extern "C" { +#endif + +#define ulock_device(lck) ulock_file(lck) + +typedef enum +{ + FC_NONE, + FC_HARD, + FC_SOFT, + FC_FULL +} FLOWCONTROL; + +#ifdef __NAMESPACE +#define lock_device __NAMESPACE(lock_device) +#define setspeed __NAMESPACE(setspeed) +#define setformat __NAMESPACE(setformat) +#define setflowctrl __NAMESPACE(setflowctrl) +#define waitfor __NAMESPACE(waitfor) +#define waitsync __NAMESPACE(waitsync) +#define input __NAMESPACE(input) +#define dropdtr __NAMESPACE(dropdtr) +#define inkey __NAMESPACE(inkey) +#define interactive __NAMESPACE(interactive) +#define readcrc __NAMESPACE(readcrc) +#define writecrc __NAMESPACE(writecrc) +#define readcsum __NAMESPACE(readcsum) +#define writecsum __NAMESPACE(writecsum) +#define xmit __NAMESPACE(xmit) +#define empty __NAMESPACE(empty) +#endif + +stty_t getstty(fd_t fd); +void putstty(fd_t fd, stty_t stty, bool now); +int setspeed(stty_t stty, ulong speed); +int setformat(stty_t stty, char *format); +int setflowctrl(stty_t stty, FLOWCONTROL flow); +int waitfor(fd_t fd, uchar *str, size_t len, int timeout, ulong maxbytes); +int waitsync(fd_t fd, uchar *list, size_t len, int timeout, ulong maxbytes); +int input(fd_t fd, uchar *buf, size_t len, int timeout, const uchar *term); +int dropdtr(fd_t fd); +int inkey(fd_t fd, int timeout); +bool interactive(stty_t stty, bool mode); +int xmit(fd_t fd, char *str); +void empty(fd_t fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/dev/waitfor.c b/sdk/dev/waitfor.c new file mode 100644 index 0000000..36fabec --- /dev/null +++ b/sdk/dev/waitfor.c @@ -0,0 +1,39 @@ +/* + * Wait for specified input from device. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions on redistribution and reuse see product license. + */ + +#include <dev/tty.h> +#include <std/string.h> + +int waitfor(int fd, uchar *list, size_t len, int timeout, ulong max) +{ + int key; + int idx = 0; + uchar *mem = (uchar *)malloc(len); + + while(max--) + { + key = inkey(fd, timeout); + if(key < 0) + return key; + + if(idx < len) + mem[idx++] = (uchar)(key & 0xff); + else + { + for(idx = 0; idx < len; ++idx) + mem[idx] = mem[idx + 1]; + + mem[len - 1] = (uchar)(key & 0xff); + } + if(!memcmp(mem, list, len)) + return 0; + } + return -1; +} + + + diff --git a/sdk/dev/waitsync.c b/sdk/dev/waitsync.c new file mode 100644 index 0000000..f4596e1 --- /dev/null +++ b/sdk/dev/waitsync.c @@ -0,0 +1,32 @@ +/* + * Wait for a sync input value from a device. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <dev/tty.h> + +int waitsync(int fd, uchar *list, size_t len, int timeout, ulong max) +{ + int key; + int idx; + uchar buf; + + while(max--) + { + key = inkey(fd, timeout); + if(key < 0) + return key; + + buf = (uchar)(key & 0xff); + + for(idx = 0; idx < len; ++idx) + if(list[idx] == buf) + return buf; + } + return -1; +} + + + diff --git a/sdk/dev/xmit.c b/sdk/dev/xmit.c new file mode 100644 index 0000000..471736d --- /dev/null +++ b/sdk/dev/xmit.c @@ -0,0 +1,31 @@ +/* + * Write output to a device and ignore any incoming (echo) data. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <dev/tty.h> + +int xmit(int fd, char *str) +{ + int len = strlen(str); + int stat; + + while(inkey(fd, 2) > -1) + continue; + + stat = write(fd, str, len); + if(stat < 0) + return stat; + + len = stat; + while(len--) + if(inkey(fd, 0) < 0) + break; + + return stat; +} + + + diff --git a/sdk/net/Makefile.in b/sdk/net/Makefile.in new file mode 100644 index 0000000..bc890f5 --- /dev/null +++ b/sdk/net/Makefile.in @@ -0,0 +1,19 @@ +# +# Template to build net makefile. +# $Id$ +# Copyright (c) 1997 by Tycho Softworks. +# + +OBJS = snmptrap.o gethost.o getservice.o getsocket.o sockname.o \ + tcpsocket.o udpsocket.o init.o tcpstream.o msgport.o netaddr.o + +.c.o: + $(CC) $(CFLAGS) $(OPTIMIZE) -I.. -o $@ -c $< + $(AR) r ../lib/libnet.a $@ + +all: $(OBJS) + ranlib ../lib/libnet.a + +clean: + rm *.o + diff --git a/sdk/net/bind.conf b/sdk/net/bind.conf new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sdk/net/bind.conf diff --git a/sdk/net/gethost.c b/sdk/net/gethost.c new file mode 100644 index 0000000..f74997c --- /dev/null +++ b/sdk/net/gethost.c @@ -0,0 +1,39 @@ +/* + * Portable and simple host name lookup fuction. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <net/socket.h> + +struct hostent *gethost(const char *hostname) +{ + static struct in_addr saddr; + struct hostent *hp; + static struct hostent np; + static char host[24]; + static char *alias[] = {NULL}; + static struct in_addr *alist[] = {&saddr, NULL}; + + if(!hostname) + return NULL; + + if(isdigit(*hostname)) + { + saddr.s_addr = inet_addr(hostname); + hp = gethostbyaddr((void *)&saddr, sizeof(struct in_addr), AF_INET); + if(hp) + return hp; + + strcpy(host, hostname); + np.h_name = host; + np.h_aliases = alias; + np.h_addrtype = AF_INET; + np.h_length = 4; + np.h_addr_list = (char **)alist; + return &np; + } + else + return gethostbyname(hostname); +} diff --git a/sdk/net/getservice.c b/sdk/net/getservice.c new file mode 100644 index 0000000..fed448e --- /dev/null +++ b/sdk/net/getservice.c @@ -0,0 +1,45 @@ +/* + * Simple portable service name lookup. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <net/socket.h> +#include <std/string.h> + +int getservice(const char *service) +{ + char servname[32]; + char *p; + struct servent *svc; + struct protoent *proto; + + if(isdigit(*service)) + return atoi(service); + + strcpy(servname, service); + p = strchr(servname, '/'); + if(!p) + strcat(servname, "/tcp"); + + p = strchr(servname, '/'); + *(p++) = 0; + if(isdigit(*p)) + { + proto = getprotobynumber(atoi(p)); + if(!proto) + return 0; + + p = proto->p_name; + } + svc = getservbyname(servname, p); + if(!svc) + return 0; + + return ntohs(svc->s_port); +} + + + + diff --git a/sdk/net/getsocket.c b/sdk/net/getsocket.c new file mode 100644 index 0000000..83ca68a --- /dev/null +++ b/sdk/net/getsocket.c @@ -0,0 +1,43 @@ +#include <net/socket.h> +#include <std/string.h> + +SOCKET getsocket(const char *host, int port, int socktype) +{ + SOCKET so; + struct hostent *hp; + struct sockaddr_in saddr; + struct in_addr *aptr; + char *sp, *p; + char *dup = strdup(host); + + so = socket(AF_INET, socktype, 0); + if(so == INVALID_SOCKET) + { + free(dup); + return so; + } + + sp = dup; + while(NULL != (p = strtok(sp, " ;:\t"))) + { + sp = NULL; + hp = gethost(p); + if(!hp) + continue; + + saddr.sin_family = hp->h_addrtype; + saddr.sin_port = htons(port); + while( (aptr = (struct in_addr *)*(hp->h_addr_list)++) != NULL) + saddr.sin_addr = *aptr; + + if(connect(so, (struct sockaddr *)&saddr, sizeof(saddr))) + continue; + + free(dup); + return so; + } + endsocket(so); + free(dup); + return INVALID_SOCKET; +} + diff --git a/sdk/net/init.c b/sdk/net/init.c new file mode 100644 index 0000000..02575a7 --- /dev/null +++ b/sdk/net/init.c @@ -0,0 +1,20 @@ +/* + * Needed for "winsock" compatibility only. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <net/socket.h> + +bool init_socket(void) +{ + return TRUE; +} + +void endsocket(SOCKET so) +{ + shutdown(so, 2); + close(so); +} + diff --git a/sdk/net/make.conf b/sdk/net/make.conf new file mode 100644 index 0000000..36fbb70 --- /dev/null +++ b/sdk/net/make.conf @@ -0,0 +1,4 @@ +if test -f $CONFIG_HOST/lib/libsocket.a ; then + CONFIG_LIBS=$CONFIG_LIBS' -lsocket' +fi + diff --git a/sdk/net/msgport.c b/sdk/net/msgport.c new file mode 100644 index 0000000..39c1109 --- /dev/null +++ b/sdk/net/msgport.c @@ -0,0 +1,84 @@ +/* + * Portable network messaging routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <net/msgport.h> +#include <std/time.h> + +static ushort sequence = 0; + +SOCKET create_msgport(char *mask, int port, int backlog) +{ + if(backlog) + return tcpsocket(mask, port, backlog); + else + return udpsocket(mask, port); +} + +size_t send_msgport(SOCKET so, SOCKMSG *buf, size_t len, bool flag) +{ + size_t stat; + + memset(buf, 0, sizeof(SOCKMSG)); + if(flag) + ++sequence; + buf->header.len = htonl(len); + buf->sequence = sequence; + + stat = send(so, buf, len + sizeof(SOCKMSG), 0); + if (stat > 0) + return stat - sizeof(SOCKMSG); + return stat; +} + +size_t recv_msgport(SOCKET so, SOCKMSG *buf, size_t len, bool any) +{ + int alen; + size_t mlen; + size_t stat; + SOCKMSG saddr; + + for(;;) + { + alen = recv(so, &saddr, sizeof(saddr), MSG_PEEK); + if(alen < 0) + return stat; + + mlen = ntohl(saddr.header.len); + if (mlen > len) + mlen = len; + + stat = recvfrom(so, buf, mlen + sizeof(saddr), 0, (struct sockaddr *)&saddr, &alen); + memcpy(buf, &saddr, alen); + if (stat > 0) + { + if(any && buf->sequence != sequence) + continue; + + return stat - sizeof(SOCKMSG); + } + return stat; + } +} + +size_t reply_msgport(SOCKET so, SOCKMSG *buf, SOCKMSG *org, size_t len) +{ + size_t stat; + SOCKMSG saddr; + + if(!org) + org = buf; + + memcpy(&saddr, org, sizeof(saddr)); + buf->header.len = htonl(len); + stat = sendto(so, buf, len + sizeof(SOCKMSG), 0, (struct sockaddr *)&saddr, sizeof(saddr)); + if (stat > 0) + return stat - sizeof(SOCKMSG); + return stat; +} + + + diff --git a/sdk/net/msgport.h b/sdk/net/msgport.h new file mode 100644 index 0000000..f7817e4 --- /dev/null +++ b/sdk/net/msgport.h @@ -0,0 +1,47 @@ +/* + * Portable network messaging routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __NET_MSGPORT_H__ +#define __NET_MSGPORT_H__ + +#ifndef __NET_SOCKET_H__ +#include <net/socket.h> +#endif + +typedef struct +{ + union + { + struct sockaddr_in addr; + long len; + } header; + ushort sequence; + uchar body[ EMPTY ]; +} SOCKMSG; + +/* msgport control options */ + +enum +{ + MSGPORT_TIMEOUT +}; + +#define attach_tcp(host, port) getsocket(host, port, SOCK_STREAM) +#define attach_udp(host, port) getsocket(host, port, SOCK_DGRAM) + +#ifdef __NAMESPACE +#define create_msgport __NAMESPACE(create_msgport) +#define send_msgport __NAMESPACE(send_msgport) +#define recv_msgport __NAMESPACE(recv_msgport) +#define reply_msgport __NAMESPACE(reply_msgport) +#endif + +SOCKET create_msgport(char *mask, int port, int backlog); +size_t send_msgport(SOCKET so, SOCKMSG *buf, size_t len, bool inc); +size_t recv_msgport(SOCKET so, SOCKMSG *buf, size_t maxlen, bool any); +size_t reply_msgport(SOCKET so, SOCKMSG *buf, SOCKMSG *org, size_t len); +#endif diff --git a/sdk/net/netaddr.c b/sdk/net/netaddr.c new file mode 100644 index 0000000..c156505 --- /dev/null +++ b/sdk/net/netaddr.c @@ -0,0 +1,28 @@ +/* + * Convert network mask or address string into a "BIND" filter mask. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <net/socket.h> +#include <std/string.h> + +struct in_addr *getnetaddr(const char *mask) +{ + static struct in_addr addr; + struct in_addr *aptr; + struct hostent *hp; + + if(!mask) + mask = "0.0.0.0"; + + hp = gethost(mask); + if(!hp) + return NULL; + + while((aptr = (struct in_addr *)*(hp->h_addr_list)++) != NULL) + addr = *aptr; + + return &addr; +} diff --git a/sdk/net/snmptrap.c b/sdk/net/snmptrap.c new file mode 100644 index 0000000..17c9f7c --- /dev/null +++ b/sdk/net/snmptrap.c @@ -0,0 +1,165 @@ +/* + * Generic snmp trap generation routine. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <net/trap.h> +#include <std/string.h> + +int snmptrap(char *host, char *agent, char *community, int id, char *enterprise, char *describe, long ut) +{ + static uchar sysvar[] = {0x06, 0x08, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00, 0x04}; + + uchar pkt[256] = {0x30, 0x82, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04}; + char console[129]; + int len; + int pos; + int l1 = 45; + int l2 = 39; + int l3 = 16; + int l2pos; + int l3pos; + int v1; + char *p; + int v2; + ulong hostip; + struct hostent *hp; + struct sockaddr_in target; + struct in_addr *aptr; + int i1, i2; + SOCKET so; + + if(!describe) + describe = ""; + + if(!host) + host = "localhost"; + + if(!agent) + agent = "localhost"; + + hp = gethost(agent); + if(!hp) + return -1; + + while( (aptr = (struct in_addr *)*(hp->h_addr_list)++) != NULL) + memcpy(&hostip, aptr, 4); + + if(!community) + community = "PUBLIC"; + + if(!enterprise) + enterprise = "1.3.6.1.4.1.3.1.1"; + + + so = socket(AF_INET, SOCK_DGRAM, 0); + if(so == INVALID_SOCKET) + return -1; + + len = strlen(community); + l1 = l1 + len + 1; + pkt[8] = (uchar)len; + strcpy((char *)pkt + 9, community); + pos = 9 + len; + pkt[pos++] = 0xa4; + l2pos = pos++; + pkt[pos++] = 0x06; + len = 0; + + v1 = atoi(enterprise); + enterprise = strchr(enterprise, '.'); + v2 = atoi(++enterprise); + len = 1; + pkt[pos + len] = (uchar)(v1 * 40 + v2); + + while(NULL !=(enterprise = strchr(enterprise, '.'))) + pkt[pos + (++len)] = (uchar)atoi(++enterprise); + + pkt[pos] = len; + pos += len + 1; + l1 += len; + l2 += len; + + pkt[pos++] = 0x40; + pkt[pos++] = 0x04; + memcpy(pkt + pos, &hostip, 4); + pos += 4; + + i2 = 0; + i1 = id; + if(id > 5 || id < 0) + { + i1 = 6; + i2 = abs(id); + } + + pkt[pos++] = 0x02; + pkt[pos++] = 0x01; + pkt[pos++] = (uchar)i1; + pkt[pos++] = 0x02; + if(i2 > -1 && i2 < 128) + { + pkt[pos++] = 0x01; + pkt[pos++] = (uchar)i2; + } + else + { + pkt[pos++] = 0x02; + pkt[pos++] = (uchar)(i2 / 256); + pkt[pos++] = (uchar)(i2 % 256); + ++l1; + ++l2; + } + pkt[pos++] = 0x43; + pkt[pos++] = 0x03; + pkt[pos++] = (uchar)((ut / 0x10000) % 256); + pkt[pos++] = (uchar)((ut / 0x100) % 256); + pkt[pos++] = (uchar)(ut % 256); + pkt[pos++] = 0x30; + pkt[pos++] = 0x82; + pkt[pos++] = 0; + l3pos = pos++; + + len = strlen(describe); + pkt[pos++] = 0x30; + pkt[pos++] = 0x82; + pkt[pos++] = 0x00; + pkt[pos++] = len + 12; + memcpy(pkt + pos, sysvar, 11); + pos += 11; + pkt[pos++] = (uchar)len; + strcpy((char *)pkt + pos, describe); + + l1 += len; + l2 += len; + l3 += len; + pos += len; + + pkt[2] = (uchar)(l1 / 256); + pkt[3] = (uchar)(l1 % 256); + pkt[l2pos] = (uchar)l2; + pkt[l3pos] = (uchar)l3; + + + strcpy(console, host); + host = strtok(console, ":\t; \t\n"); + while(NULL != host) + { + hp = gethost(host); + if(!hp) + return -1; + + while( (aptr = (struct in_addr *)*(hp->h_addr_list)++) != NULL) + target.sin_addr = *aptr; + + target.sin_family = hp->h_addrtype; + target.sin_port = htons(SNMP_TRAP_PORT); + host = strtok(NULL, ":\t;"); + sendto(so, pkt, pos, 0, (struct sockaddr *)&target, sizeof(struct sockaddr)); + } + endsocket(so); + return 0; +} + diff --git a/sdk/net/socket.h b/sdk/net/socket.h new file mode 100644 index 0000000..b9bd190 --- /dev/null +++ b/sdk/net/socket.h @@ -0,0 +1,61 @@ +/* + * Portable include for access of socket services. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __NET_SOCKET_H__ +#define __NET_SOCKET_H__ + +#ifndef __STD_FILES_H__ +#include <std/files.h> +#endif + +#ifndef __STD_TYPES_H__ +#include <std/types.h> +#endif + +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> + +typedef int SOCKET; +#define INVALID_SOCKET -1 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __NAMESPACE +#define init_sockets __NAMESPACE(init_sockets) +#define gethost __NAMESPACE(gethost) +#define getservice __NAMESPACE(getservice) +#define peername __NAMESPACE(peername) +#define peeraddr __NAMESPACE(peeraddr) +#define homename __NAMESPACE(homename) +#define homeaddr __NAMESPACE(homeaddr) +#define endsocket __NAMESPACE(endsocket) +#define udpsocket __NAMESPACE(udpsocket) +#define tcpsocket __NAMESPACE(tcpsocket) +#define getsocket __NAMESPACE(getsocket) +#endif + +bool init_sockets(void); +struct hostent *gethost(const char *host); +struct in_addr *getnetaddr(const char *addr); +int getservice(const char *service); +char *peername(SOCKET so); +char *peeraddr(SOCKET so); +char *homename(SOCKET so); +char *homeaddr(SOCKET so); +void endsocket(SOCKET so); +SOCKET udpsocket(char *mask, int port); +SOCKET tcpsocket(char *mask, int port, int backlog); +SOCKET getsocket(const char *host, int port, int socktype); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/net/sockname.c b/sdk/net/sockname.c new file mode 100644 index 0000000..a8e9aad --- /dev/null +++ b/sdk/net/sockname.c @@ -0,0 +1,62 @@ +/* + * Portable socket and peer name services. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <net/socket.h> + +char *homename(SOCKET so) +{ + struct hostent *hp; + struct sockaddr_in sin; + int len = sizeof(sin); + + if(getsockname(so, (struct sockaddr *)&sin, &len) < 0) + return NULL; + + hp = gethostbyaddr((char *)&sin.sin_addr, sizeof(struct in_addr), AF_INET); + if(hp) + return (char *)hp->h_name; + else + return inet_ntoa(sin.sin_addr); +} + +char *homeaddr(SOCKET so) +{ + struct sockaddr_in sin; + int len = sizeof(sin); + + if(getsockname(so, (struct sockaddr *)&sin, &len) < 0) + return NULL; + + return inet_ntoa(sin.sin_addr); +} + +char *peername(SOCKET so) +{ + struct hostent *hp; + struct sockaddr_in sin; + int len = sizeof(sin); + + if(getpeername(so, (struct sockaddr *)&sin, &len) < 0) + return NULL; + + hp = gethostbyaddr((char *)&sin.sin_addr, sizeof(struct in_addr), AF_INET); + if(hp) + return (char *)hp->h_name; + else + return inet_ntoa(sin.sin_addr); +} + +char *peeraddr(SOCKET so) +{ + struct sockaddr_in sin; + int len = sizeof(sin); + + if(getpeername(so, (struct sockaddr *)&sin, &len) < 0) + return NULL; + + return inet_ntoa(sin.sin_addr); +} diff --git a/sdk/net/stream.h b/sdk/net/stream.h new file mode 100644 index 0000000..268d881 --- /dev/null +++ b/sdk/net/stream.h @@ -0,0 +1,45 @@ +/* + * Stream oriented TCP session routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __NET_STREAM_H__ +#define __NET_STREAM_H__ + +#ifndef __NET_SOCKET_H__ +#include <net/socket.h> +#endif + +#define tcppeer(fp) peername(fileno(fp)) +#define tcphome(fp) homename(fileno(fp)) + +typedef FILE *STREAM; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __NAMESPACE +#define opentcp __NAMESPACE(opentcp) +#define accepttcp __NAMESPACE(accepttcp) +#define gettcp __NAMESPACE(gettcp) +#define puttcp __NAMESPACE(puttcp) +#define closetcp __NAMESPACE(closetcp) +#define buftcp __NAMESPACE(buftcp) +#endif + +STREAM opentcp(const char *hostname, int port); +STREAM accepttcp(SOCKET so); +char *gettcp(char *buf, size_t count, STREAM fp); +int puttcp(char *str, STREAM fp); +void closetcp(STREAM fp); +int buftcp(STREAM fp, int size); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/sdk/net/tcpsocket.c b/sdk/net/tcpsocket.c new file mode 100644 index 0000000..b5e61bf --- /dev/null +++ b/sdk/net/tcpsocket.c @@ -0,0 +1,42 @@ +/* + * Create and bind a tcp socket for a server. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <net/socket.h> + +SOCKET tcpsocket(char *mask, int port, int backlog) +{ + SOCKET so; + struct sockaddr_in saddr; + struct in_addr *aptr; + + so = socket(AF_INET, SOCK_STREAM, 0); + if(so == INVALID_SOCKET) + return so; + + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + aptr = getnetaddr(mask); + if(!aptr) + { + endsocket(so); + return INVALID_SOCKET; + } + saddr.sin_addr = *aptr; + + if(bind(so, (struct sockaddr *)&saddr, sizeof(saddr))) + { + endsocket(so); + return INVALID_SOCKET; + } + if(listen(so, backlog)) + { + endsocket(so); + return INVALID_SOCKET; + } + return so; +} diff --git a/sdk/net/tcpstream.c b/sdk/net/tcpstream.c new file mode 100644 index 0000000..b39645d --- /dev/null +++ b/sdk/net/tcpstream.c @@ -0,0 +1,88 @@ +/* + * Portable TCP session stream functions. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <net/stream.h> +#include <std/string.h> + +STREAM opentcp(const char *host, int port) +{ + SOCKET so = getsocket(host, port, SOCK_STREAM); + FILE *fp; + + if(so == INVALID_SOCKET) + return NULL; + + fp = fdopen(so, "r+"); + if(!fp) + { + endsocket(so); + return NULL; + } + buftcp(fp, 0); + return fp; +} + +char *gettcp(char *buf, size_t count, STREAM fp) +{ + memset(buf, 0, count); + if(!fgets(buf, count, fp)) + return NULL; + + return buf; +} + +int puttcp(char *buf, STREAM fp) +{ + int err; + err = fputs(buf, fp); + fflush(fp); + return err; +} + +void closetcp(STREAM fp) +{ + SOCKET so = fileno(fp); + + fflush(fp); + shutdown(so, 2); + fclose(fp); +} + +int buftcp(STREAM fp, int size) +{ + fflush(fp); + + if(!size) + return setvbuf(fp, NULL, _IOLBF, 1024); + else + return setvbuf(fp, NULL, _IOFBF, size); +} + +STREAM accepttcp(SOCKET so) +{ + struct sockaddr addr; + int len; + int si; + FILE *fp; + + len = sizeof(addr); + si = accept(so, &addr, &len); + if(si < 0) + return NULL; + + fp = fdopen(si, "r+"); + if(!fp) + { + shutdown(si, 2); + close(si); + return NULL; + } + + buftcp(fp, 0); + return fp; +} + diff --git a/sdk/net/trap.h b/sdk/net/trap.h new file mode 100644 index 0000000..b903d5d --- /dev/null +++ b/sdk/net/trap.h @@ -0,0 +1,30 @@ +/* + * Define SNMP Traps. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __NET_TRAP_H__ + +#ifndef __NET_SOCKET_H__ +#include <net/socket.h> +#endif + +#define SNMP_TRAP_PORT 162 +#define SNMP_TRAP_COLDSTART 0 +#define SNMP_TRAP_WARMSTART 1 +#define SNMP_TRAP_LINKDOWN 2 +#define SNMP_TRAP_LINKUP 3 +#define SNMP_TRAP_AUTHFAIL 4 +#define SNMP_TRAP_EGPNEIGHBORLOSS 5 +#define SNMP_TRAP_ENTERPRISESPECIFIC 6 + +#ifdef __NAMESPACE +#define snmptrap __NAMESPACE(snmptrap) +#endif + +int snmptrap(char *target, char *host, char *community, int id, char *enterprise, char *describe, long uptime); + + +#endif diff --git a/sdk/net/udpsocket.c b/sdk/net/udpsocket.c new file mode 100644 index 0000000..2127ac3 --- /dev/null +++ b/sdk/net/udpsocket.c @@ -0,0 +1,36 @@ +/* + * Create and bind a udp socket for a server. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <net/socket.h> + +SOCKET udpsocket(char *mask, int port) +{ + SOCKET so; + struct sockaddr_in saddr; + struct in_addr *aptr; + + so = socket(AF_INET, SOCK_DGRAM, 0); + if(so == INVALID_SOCKET) + return so; + + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + aptr = getnetaddr(mask); + if(!aptr) + { + endsocket(so); + return INVALID_SOCKET; + } + saddr.sin_addr = *aptr; + + if(bind(so, (struct sockaddr *)&saddr, sizeof(saddr))) + { + endsocket(so); + return INVALID_SOCKET; + } + return so; +} diff --git a/sdk/other/Makefile.in b/sdk/other/Makefile.in new file mode 100644 index 0000000..17dd18a --- /dev/null +++ b/sdk/other/Makefile.in @@ -0,0 +1,22 @@ +# +# Template to build our "other" object modules(libother.a) +# $Id: Makefile.in 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $ +# Copyright (c) 1997 by Tycho Softworks. +# + +OBJS = memalloc.o memdup.o memfree.o mempool.o memrelease.o \ + memreq.o config.o confdir.o bcd.o env.o atob.o strint.o \ + expand.o picture.o xval.o hex.o strcopy.o strdiff.o \ + strblank.o strpos.o strreq.o strtrim.o ccount.o filename.o \ + isftype.o getargv.o search.o token.o fatal.o fncat.o + +.c.o: + $(CC) $(CFLAGS) $(OPTIMIZE) -I.. -o $@ -c $< + $(AR) r ../lib/libother.a $@ + +all: $(OBJS) + ranlib ../lib/libother.a + +clean: + rm *.o + diff --git a/sdk/other/atob.c b/sdk/other/atob.c new file mode 100644 index 0000000..1535f7a --- /dev/null +++ b/sdk/other/atob.c @@ -0,0 +1,47 @@ +/* + * Convert ASCII text into binary value. + * $Id: atob.c 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and use, see product license. + * + * Functions: + * atob() - convert null terminated ASCII string to boolean value. + */ + +#include <other/strcvt.h> + +/* + * Convert null terminated ASCII string to boolean value. + * + * Abstract: + * The input string can be numeric; such as "0" or "1", or alpha; + * such as "T" for true, "F" for false, or "Y" or "N". Only the + * first character of the string is examined. Upper/lower case is + * ignored. + * + * Parameters: + * str - null terminated ASCII string. + * + * Returns: + * logical value of input string. + * + * Exceptions: + * Any unrecognized string value, or a NULL string, return FALSE. + */ + +bool atob(const char *str) +{ + if(!str) + return FALSE; + + switch(*str) + { + case '0': + case 'f': + case 'F': + case 'n': + case 'N': + return FALSE; + } + return TRUE; +} diff --git a/sdk/other/bcd.c b/sdk/other/bcd.c new file mode 100644 index 0000000..3bd6144 --- /dev/null +++ b/sdk/other/bcd.c @@ -0,0 +1,125 @@ +/* + * Convert ASCII numbers to or from BCD representations. + * $Id: bcd.c 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For condititions of distribution and use, see product license. + * + * Abstract: + * BCD is a format for storing packed decimal data within a nibble. + * We assume "big endian" BCD, in that the high nibble contains the + * first digit within a byte. Any unused digits are filled with the + * nibble value of $F. This module provides the services needed to + * convert BCD data to and from ASCII strings. + * + * Functions: + * str2bcd() - convert ASCII string to packed bcd. + * bcd2str() - convert packed bcd to ASCII string. + */ + +#include <other/strcvt.h> + +/* + * Convert null terminated ASCII string to packed bcd data. + * + * Abstract: + * An ASCII input string is converted to binary packed decimal + * data. Any unused digits are filled with $f. The size specified + * for digits is filled, either with available digits from the input + * string, or with $f nibbles once no more digits are available. + * + * Paramaters: + * bcd - pointer to start of bcd data to store. + * str - null terminated input string. + * max - maximum number of digits in bcd data. + * + * Returns: + * pointer to first non-BCD digit in input string. + * + * Exceptions: + * If NULL input string, returns NULL. If more digits exist in + * the input string than are available in bcd storage (data + * overflow), the remaining digits are ignored. + */ + +char *str2bcd(uchar *bcd, char *str, int max) +{ + uchar packed = 0xff; + bool low = FALSE; + + if(!str) + return NULL; + + while(isdigit(*str)) + { + packed = packed / 16; + packed |= ((*(str++) - '0') * 16); + if(low) + { + *(bcd++) = packed; + packed = 0xff; + if(!--max) + return str; + + low = FALSE; + } + else + low = TRUE; + } + if(low) + { + *(bcd++) = packed; + --max; + } + while(max--) + *(bcd++) = 0xff; + + return str; +} + +/* + * Convert binary coded data to ASCII text. + * + * Abstract: + * A block of bcd data of up to a specified length is read, each + * digit being converted to an ASCII character code. If a $f is + * found before 'len' digits are examined, then the program + * completes with a shorter number. + * + * Paramaters: + * str - start of output string to receive converted data. + * bcd - bcd data input. + * len - maximum number of bcd digits. + * + * Return: + * pointer to next available bcd number in memory (or past end of + * bcd data block). The output string (str) is also given a null + * terminating byte. + * + * Exceptions: + * A NULL bcd pointer returns a NULL string. + */ + +uchar *bcd2str(char *str, uchar *bcd, int len) +{ + uchar nib1, nib2; + if(!bcd) + return NULL; + + while(len--) + { + nib1 = *bcd / 16; + nib2 = *bcd % 16; + if(nib1 < 16) + *(str++) = nib1 + '0'; + else + break; + if(nib2 < 16) + *(str++) = nib2 + '0'; + else + break; + ++bcd; + } + *str = 0; + return bcd; +} + diff --git a/sdk/other/bind.conf b/sdk/other/bind.conf new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/sdk/other/bind.conf @@ -0,0 +1 @@ + diff --git a/sdk/other/ccount.c b/sdk/other/ccount.c new file mode 100644 index 0000000..ec53a98 --- /dev/null +++ b/sdk/other/ccount.c @@ -0,0 +1,45 @@ +/* + * Count character occurances in string. + * $Id: ccount.c 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and use see product license. + * + * Functions: + * ccount() - count characters in string. + */ + +#include <other/string.h> + +/* + * Count character occurances in ASCII string. + * + * Abstract: + * A list of possible characters to look for is passed to ccount, + * along with the null terminated ASCII string to look for those + * characters within. + * + * Parameters: + * str - string to examine and count occurances in. + * list - list (null terminated) of characters to search for. + * + * Exceptions: + * Either a NULL list or string is considered to hold no found + * characters (returns 0). + */ + +int ccount(const char *str, const char *list) +{ + int count = 0; + + if(!str || !list) + return 0; + + while(NULL != (str = strpbrk(str, list))) + { + ++count; + ++str; + } + return count; +} + + diff --git a/sdk/other/confdir.c b/sdk/other/confdir.c new file mode 100644 index 0000000..cabc475 --- /dev/null +++ b/sdk/other/confdir.c @@ -0,0 +1,105 @@ +/* + * Routines to access directory of section names in a config file. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and use see product license. + * + * Abstract: + * These routines may be used to scan the 'directory' of [] section + * names within a config file, much like the MS-DOS find_first() and + * find_next() directory routines. + * + * Functions: + * this_config() - internal routine to return section name. + * first_config() - goto first named [] section within the config file. + * next_config() - skip to the next named [] section. + */ + +#include <other/config.h> +#include <other/string.h> +#include <other/env.h> + +#ifndef LBUF +#define LBUF 1024 +#endif + +/* + * Internal program to support parsing of found section name. + */ + +static char *this_config(CONFIG *cfg) +{ + char *p; + + if(feof(cfg->cfg_fp)) + return NULL; + + if(cfg->cfg_lbuf[0] != '[') + return NULL; + + cfg->cfg_flag = TRUE; + p = strtok(cfg->cfg_lbuf, "[]\n\r"); + return p; +} + +/* + * Automatically seek the very first [] section within a config file. + * + * Paramaters: + * cfg - config object pointer. + * + * Returns: + * Name string of first [] name in config file. + * + * Exceptions: + * If no [] section in config file, NULL cfg pointer, or file + * error, returns NULL. + */ + +char *first_config(CONFIG *cfg) +{ + if(!cfg) + return NULL; + + fseek(cfg->cfg_fp, 0l, SEEK_SET); + return next_config(cfg); +} + +/* + * Skip to the next named [] section within a config file. + * + * Paramaters: + * cfg - config object pointer. + * + * Returns: + * Name string of next named [] section in config file. + * + * Exceptions: + * Returns NULL if cfg invalid or end of file reached. + * + */ + +char *next_config(CONFIG *cfg) +{ + if(!cfg) + return NULL; + + if(feof(cfg->cfg_fp)) + return NULL; + + for(;;) + { + fgets(cfg->cfg_lbuf, LBUF - 1, cfg->cfg_fp); + if(feof(cfg->cfg_fp)) + return NULL; + + if(cfg->cfg_lbuf[0] == '[') + return this_config(cfg); + } +} + + + + + + diff --git a/sdk/other/config.c b/sdk/other/config.c new file mode 100644 index 0000000..e274b85 --- /dev/null +++ b/sdk/other/config.c @@ -0,0 +1,437 @@ +/* + * Routines to access and parse standard text config files. + * $Id: config.c 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and use see product license. + * + * Abstract: + * These routines are used to open and parse human readable '.conf' + * files, such as those which may be stored in the /etc directory. + * The .conf file is parsed as a sectioned text file, with the name + * for each logical section appearing in []'s. Entries within each + * section are typically in the format 'keyword = value', though + * there are exceptions for multi-line fixed size lists, in + * the form 'keyword = { list }', and repeated lines. Comments may + * also appear within .conf files. + * + * Functions: + * sys_config() - find and open a /etc or /etc/prior .conf file. + * open_config() - open any text file as a config file. + * read_config() - read a keyword = value pair from current section. + * seek_config() - seek a named [] section within the config file. + * get_config() - tests current input for a specified keyword. + * usr_config() - user specific resource config file. + */ + +#include <other/config.h> +#include <other/strcvt.h> +#include <other/string.h> +#include <other/env.h> +#include <std/process.h> + +/* + * When searching for 'system' .conf files, which are normally held in + * /etc, also search in /etc/prior. This is used so that a human + * readable .conf file can momentarily be moved into '/etc/prior' and + * still be usable while a GUI system management program is in the middle + * building a new .conf file. + */ + +#ifndef CFGPATH +#define CFGPATH "/etc:/etc/prior" +#endif + +/* + * Maximum working space for single or multi-line input records being + * parsed. + */ + +#ifndef LBUF +#define LBUF 1024 +#endif + +#ifndef SUFFIX +#define SUFFIX ".conf" +#endif + +/* + * Open a system .conf file, as found in the system config directories. + * + * Abstract: + * This function finds a .conf file in either the /etc or /etc/prior + * directory. /etc/prior is searched if the current .conf file is + * not found (in /etc), as may happen if it is in the middle of + * being re-built by a management application. This provides an + * initial function which may be used to open most .conf files. + * + * Paramaters: + * cfg_name - 'base' filename of system .conf file to open. + * + * Returns: + * pointer to active CONFIG object for specified filename. + * + * Exceptions: + * If the file is not found, a NULL pointer is returned. + */ + +CONFIG *sys_config(const char *cfg_name) +{ + char cfgname[PATH_MAX + 1]; + + strcpy(cfgname, cfg_name); + strcat(cfgname, SUFFIX); + return open_config(search(CFGPATH, cfgname)); +} + +/* + * Open any specified filename as a .conf file. + * + * Abstract: + * This function opens the specified file as a 'config' file for use + * in config file parsing routines. Any filename may be specified + * and opened as a config file with this routine. + * + * Paramaters: + * config_name - full pathname of a .conf file to open. + * + * Returns: + * pointer to a newly allocated CONFIG parsing object for the + * specified filename. + * + * Exceptions: + * If the file is not found, a NULL pointer is returned. + */ + + +CONFIG *open_config(const char *config_name) +{ + CONFIG *new; + char *env; + + if(NULL == (new = (CONFIG *)malloc(sizeof(CONFIG) + LBUF))) + return NULL; + + if(NULL == (new->cfg_fp = fopen(config_name, "r"))) + { + free(new); + return NULL; + } + new->cfg_flag = FALSE; + return new; +} + +/* + * Close an open config file and destroy the CONFIG parser object. + */ + +void close_config(CONFIG *cfg) +{ + if(!cfg) + return; + + fclose(cfg->cfg_fp); + free(cfg); +} + +/* Read a line of ASCII text input from an open config file. + * + * Abstract: + * This routine extracts a line of input from an open config file. + * The input line extracted and returned is a "keyword = value" line + * found within the current [] section. If the end of the current + * [] section has been reached, then no further input is returned. + * + * Lines which contain comments are automatically skipped. Comments + * include those lines which begin with a '#' or ';' character. + * Empty lines are also automatically skipped. + * + * Special {} subsections may also be used to specify language + * variant .conf values. When these subsection identifiers are found + * and the current language found in the ENV (LANG=) does not match + * the language for the specified {} section, the entire {} section + * is skipped. + * + * The input line retreived automatically has lead and trailing + * whitespaces removed. + * + * Paramaters: + * cfg - a 'config' parser object. + * + * Returns: + * ASCII text for 'keyword = value' item from config file. + * + * Exceptions: + * A NULL is returned when the current [] section has been completed, + * when at the end of the file, or if any error occurs while reading. + */ + +char *read_config(CONFIG *cfg) +{ + char *p, *q; + int skip = 0; + + if(!cfg) + return NULL; + + if(!cfg->cfg_flag) + return NULL; + + for(;;) + { + fgets(cfg->cfg_lbuf, LBUF - 1, cfg->cfg_fp); + if(feof(cfg->cfg_fp) || cfg->cfg_lbuf[0] == '[' || ferror(cfg->cfg_fp)) + { + cfg->cfg_flag = FALSE; + return NULL; + } + p = strtrim(cfg->cfg_lbuf, __SPACES); + + if(*p == '{') + { + skip = 1; + p = strtok(p, "{}| \t"); + while(p) + { + if(!stricmp(p, "all")) + skip = 0; + if(!stricmp(p, language())) + skip = 0; + p = strtok(NULL, "{}| \t"); + } + continue; + } + + if(!*p || *p == '!' || *p == '#' || *p == ';' || skip) + continue; + + return p; + } +} + +/* + * Seek a named [] section within the .conf file to begin input. + * + * Abstract: + * The named section is found within the .conf file. Once + * found, all read_config() input will be returned from the + * specified [] section. Section names are case insensitive. + * + * Paramaters: + * cfg - config object pointer. + * seek_name - name of config [] section to find. + * + * Returns: + * TRUE if the section name is found in the .conf file , FALSE if + * not. + * + * Exceptions: + * If a NULL cfg or seek_name is passed, the search always fails. + * If a file error is found, the search always fails. The maximum + * size of a [] section name that is tested is 22 characters. + */ + +bool seek_config(CONFIG *cfg, const char *seek_name) +{ + char group[25]; + int len; + + if(!cfg || !seek_name) + return FALSE; + + cfg->cfg_flag = FALSE; /* mark as outside old [] section */ + + len = strlen(seek_name); + if (len > 22) + len = 22; + + memset(group, 0, sizeof(group)); + + if(*seek_name != '[') + strcpy(group, "["); + + strncat(group, seek_name, len); + + if(*seek_name != '[' && strlen(seek_name) < 23) + strcat(group, "]"); + + fseek(cfg->cfg_fp, 0l, SEEK_SET); + len = strlen(group); + for(;;) + { + fgets(cfg->cfg_lbuf, LBUF - 1, cfg->cfg_fp); + if(feof(cfg->cfg_fp) || ferror(cfg->cfg_fp)) + return FALSE; + + if(!strnicmp(group, cfg->cfg_lbuf, len)) + { + cfg->cfg_flag = TRUE; + return TRUE; + } + } +} + +/* + * Parse and test a keyword value pair from current config input. + * + * Abstract: + * This routine is commonly used to search the current input line + * that is returned by read_config() for a specified keyword. The + * current input line is assumed to be in the form 'keyword = value'. + * lead and trailing spaces around the '=' are ignored, as is keyword + * case. White spaces within a keyword are also ignored. + * + * Assuming the keyword requested is found in the current input line, + * the 'value' string is returned. If the keyword being tested is + * a multi-line keyword = { list }, then all lines for the value are + * scanned and loaded into the config line buffer. If the special + * '+' entry is found in the config file, then the keyword is assumed + * to be a continuation of the last one found. + * + * A value is normally stripped of all lead and trailing spaces. If + * these need to be preserved, then the value may be put in single + * or double quotes. + * + * Since get_config() only looks at the current input line buffered + * by read_config(), a test for every possible keyword the application + * may need should be performed after each successful read_config() + * for a given [] section. + * + * Paramaters: + * cfg - config object pointer. + * keyword - keyword to test for. + * + * Returns: + * Value string if keyword is found in current input line, else NULL. + * + * Exceptions: + * If a NULL pointer or keyword is used, a NULL value is returned. + */ + +char *get_config(CONFIG *cfg, const char *keyword) +{ + char *cbuf; + char *out, *p; + int pos = 0; + bool found = FALSE; + + if(!cfg || !keyword) + return NULL; + + cbuf = cfg->cfg_lbuf; + + if(*cbuf == '+') /* alternate multi-line syntax */ + { + if(!stricmp(cfg->cfg_test, keyword)) + return strltrim(++cbuf, __SPACES); + else + return NULL; + } + + while((pos < 33) && *cbuf && (*cbuf != '=')) + { + if((*cbuf != ' ') && (*cbuf != '_') && (*cbuf != '\t')) + cfg->cfg_test[pos++] = *(cbuf++); + else + ++cbuf; + } + cfg->cfg_test[pos] = 0; + out = p = strltrim(++cbuf, __SPACES); + switch(*p) + { + case '{': + cbuf = p; + while(!found) + { + while(*(++p)) + { + if(*p == '}') + { + found = TRUE; + *p = 0; + } + else + *(cbuf++) = *p; + } + + if(!found) + { + p = cbuf; + fgets(p, LBUF - 1 + (int)(cfg->cfg_lbuf - p), cfg->cfg_fp); + if(feof(cfg->cfg_fp) || *p == '[') + { + cfg->cfg_flag = FALSE; + *p = 0; + break; + } + *(cbuf++) = '\n'; + p = strtrim(p, __SPACES); + } + } + *cbuf = 0; + out = strltrim(++out, __SPACES); + break; + case '\'': + case '\"': + while(*(++p)) + { + if(*p == *out) + { + *p = 0; + break; + } + } + out = strltrim(++out, __SPACES); + break; + } + if(!stricmp(cfg->cfg_test, keyword)) + return out; + else + return NULL; +} + +/* + * Find config file in user's home directory. + * + * Abstract: + * In addition to searching for a master config file in /etc, many + * applications may support an optional user specific 'rc' or config + * file in the user's own home directory, which, if found, may + * override global defaults. This ability is easily supported with + * the usr_config() service, which looks for a named .config file + * in the user's home. + * + * Paramaters: + * Filename of '.config' file to look for in a user's home directory, + * without the leading '.'. + * + * Returns: + * Config object pointer if file is found in user's home, otherwise + * a NULL pointer. + * + * Exceptions: + * A NULL filename will result in a NULL object being returned. + */ + +CONFIG *usr_config(const char *name) +{ + char path[NAME_MAX + 1]; + + if(!name) + return NULL; + + strcpy(path, homedir()); + fncat(path, "."); + strcat(path, name); + return open_config(path); +} + + + + + + + + + + + diff --git a/sdk/other/config.h b/sdk/other/config.h new file mode 100644 index 0000000..4d76d1a --- /dev/null +++ b/sdk/other/config.h @@ -0,0 +1,67 @@ +/* + * Portable human readable config text file parsing routines. + * $Id: config.h 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and use see product license. + * + * Abstract: + * The config routines allow locating, opening, and parsing of + * human readable .conf files. These .conf files are broken into + * seperate named [] sections, each of which may be individually + * located and examined, and config data. Config data is usually + * in the form of a 'keyword = value' statement. + * + * Data types: + * CONFIG - object line parse buffer for an open config file. + */ + +#ifndef __OTHER_CONFIG_H__ +#define __OTHER_CONFIG_H__ + +#ifndef __OTHER_STRING_H__ +#include <other/string.h> +#endif + +#ifndef __OTHER_FILES_H__ +#include <other/files.h> +#endif + +typedef struct +{ + bool cfg_flag; + FILE *cfg_fp; + char cfg_test[33]; + char cfg_lbuf[ EMPTY ]; +} CONFIG; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __NAMESPACE +#define open_config __NAMESPACE(open_config) +#define sys_config __NAMESPACE(sys_config) +#define usr_config __NAMESPACE(usr_config) +#define first_config __NAMESPACE(first_config) +#define next_config __NAMESPACE(next_config) +#define seek_config __NAMESPACE(seek_config) +#define read_config __NAMESPACE(read_config) +#define close_config __NAMESPACE(close_config) +#define get_config __NAMESPACE(get_config) +#endif + +CONFIG *open_config(const char *name); +CONFIG *sys_config(const char *name); +CONFIG *usr_config(const char *name); +char *first_config(CONFIG *cfg); +char *next_config(CONFIG *cfg); +bool seek_config(CONFIG *cfg, const char *name); +char *read_config(CONFIG *cfg); +void close_config(CONFIG *cfg); +char *get_config(CONFIG *cfg, const char *option); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/other/env.c b/sdk/other/env.c new file mode 100644 index 0000000..cf3dfb0 --- /dev/null +++ b/sdk/other/env.c @@ -0,0 +1,36 @@ +/* + * Common values found in process environment space. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * See conditions of distribution and reuse see product license. + */ + +#include <other/env.h> +#include <std/string.h> + +char *homedir(void) +{ + char *env = getenv("HOME"); + + if(!env) + env = "/"; + + return env; +} + +char *language(void) +{ + static char lbuf[32] = "default"; + + char *env = getenv("LANG"); + + if(env) + { + strncpy(lbuf, env, 31); + lbuf[31] = 0; + strtok(lbuf, "._"); + } + return lbuf; +} + + diff --git a/sdk/other/env.h b/sdk/other/env.h new file mode 100644 index 0000000..96b70e3 --- /dev/null +++ b/sdk/other/env.h @@ -0,0 +1,31 @@ +/* + * Portable process environment routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __OTHER_ENV_H__ +#define __OTHER_ENV_H__ + +#ifndef __STD_PROCESS_H__ +#include <std/process.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __NAMESPACE +#define homedir __NAMESPACE(homedir) +#define language __NAMESPACE(language) +#endif + +char *homedir(void); +char *language(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/other/expand.c b/sdk/other/expand.c new file mode 100644 index 0000000..8005957 --- /dev/null +++ b/sdk/other/expand.c @@ -0,0 +1,36 @@ +/* + * String expansion and normalization of 'plain text' line data. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <std/string.h> + +char *expand(const char *s) +{ + static char buf[320]; + + int pos = 0; + + while(*s) + { + if(*s == '\t') + { + buf[pos++] = ' '; + while(pos % 8) + buf[pos++] = ' '; + } + else if (*s > 31) + buf[pos++] = *s; + else + { + buf[pos++] = '^'; + buf[pos++] = *s + '@'; + } + ++s; + } + buf[pos] = 0; + return buf; +} + diff --git a/sdk/other/fatal.c b/sdk/other/fatal.c new file mode 100644 index 0000000..fd3ef54 --- /dev/null +++ b/sdk/other/fatal.c @@ -0,0 +1,23 @@ +/* + * Print error message to stderr and exit with status code. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> +#include <std/files.h> +#include <std/process.h> +#include <stdarg.h> + +void fatal(int excode, const char *format, ...) +{ + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + exit(excode); +} + + diff --git a/sdk/other/filename.c b/sdk/other/filename.c new file mode 100644 index 0000000..2a7275e --- /dev/null +++ b/sdk/other/filename.c @@ -0,0 +1,74 @@ +/* + * Portable file and directory name functions. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/files.h> +#include <std/string.h> +#include <std/math.h> + +char *dirname(char *path) +{ + char *p = basename(path); + if(p == path) + return "."; + + *(--p) = 0; + return path; +} + +char *basename(const char *path) +{ + char *p = strrchr(path, '/'); +#if defined(_MSDOS) || defined(_OS2) || defined(_WIN32) + char *p1 = strrchr(path, '\\'); + p = max(p, p1); +#endif + + if(p) + return ++p; + else + return (char *)path; +} + +char *extfname(const char *path) +{ + char *e = strrchr(pathfname(path), '.'); + + if(e) + return e; + else + return ""; +} + +bool ispath(const char *p) +{ + if(strchr(p, '/')) + return TRUE; +#if defined(_MSDOS) || defined(_OS2) || defined(_WIN32) + if(strchr(p, '\\')) + return TRUE; +#endif + return FALSE; +} + +bool isroot(const char *p) +{ +#if defined(_MSDOS) || defined(_OS2) || defined(_WIN32) + if(!strncmp(p, "\\\\", 2)) + return TRUE; + + if(p[1] == ':') + return TRUE; +#else + if(*p == '/') + return TRUE; +#endif + return FALSE; +} + + + + diff --git a/sdk/other/files.h b/sdk/other/files.h new file mode 100644 index 0000000..7e9f421 --- /dev/null +++ b/sdk/other/files.h @@ -0,0 +1,52 @@ +/* + * Portable support for file manipulation and access related functions. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __OTHER_FILES_H__ +#define __OTHER_FILES_H__ + +#ifndef __STD_FILES_H__ +#include <std/files.h> +#endif + +#define isdir(fpath) isftype(fpath, S_IFDIR) +#define isfile(fpath) isftype(fpath, S_IFREG) +#define islink(fpath) isftype(fpath, S_IFLNK) +#define isfifo(fpath) isftype(fpath, S_IFIFO) +#define pathfname(fn) basename(fn) +#define rewind(fd) lseek(fd, (off_t)0, SEEK_SET) + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __NAMESPACE +#define isnewfile __NAMESPACE(isnewfile) +#define isftype __NAMESPACE(isftype) +#define ispath __NAMESPACE(ispath) +#define isroot __NAMESPACE(isroot) +#define fncat __NAMESPACE(fncat) +#define search __NAMESPACE(search) +#define basename __NAMESPACE(basename) +#define dirname __NAMESPACE(dirname) +#define extfname __NAMESPACE(extfname) +#endif + +bool isnewfile(const char *from, const char *to); +bool isftype(const char *fpath, int ftype); +bool ispath(const char *fpath); +bool isroot(const char *fpath); +char *fncat(char *prefix, const char *suffix); +char *search(const char *path, const char *fname); +char *basename(const char *path); +char *dirname(char *path); +char *extfname(const char *path); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/other/fncat.c b/sdk/other/fncat.c new file mode 100644 index 0000000..1d8e3e7 --- /dev/null +++ b/sdk/other/fncat.c @@ -0,0 +1,30 @@ +/* + * Concatenate filenames. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse review product license. + */ + +#include <std/files.h> +#include <other/string.h> + +char *fncat(char *prefix, const char *suffix) +{ + char *t = tail(prefix); + + if(!*prefix) + { + strcpy(prefix, suffix); + return prefix; + }; + + if(*(--t) != '/') + { + *(++t) = '/'; + *(++t) = 0; + } + + strcat(prefix, suffix); + return prefix; +} + diff --git a/sdk/other/getargv.c b/sdk/other/getargv.c new file mode 100644 index 0000000..bae4d4f --- /dev/null +++ b/sdk/other/getargv.c @@ -0,0 +1,57 @@ +/* + * Portable routines to create argv[] argument lists for exec and spawn. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> + +int getargv(char *base[], char *cbuf) +{ + int arg = 0; + int qflag = 0; + int sflag = 1; + + while(*cbuf) + { + switch(*cbuf) + { + case ' ': + case '\t': + if(qflag) + break; + if(!sflag) + { + *cbuf = 0; + sflag = 1; + } + break; + case '\"': + if(!qflag) + { + *cbuf = 0; + base[arg++] = cbuf + 1; + sflag = 0; + qflag = 1; + } + else + { + *cbuf = 0; + sflag = 1; + qflag = 0; + } + break; + default: + if(sflag) + { + base[arg++] = cbuf; + sflag = 0; + } + } + ++cbuf; + } + base[arg] = NULL; + return arg; +} + diff --git a/sdk/other/hex.c b/sdk/other/hex.c new file mode 100644 index 0000000..ae5ccec --- /dev/null +++ b/sdk/other/hex.c @@ -0,0 +1,44 @@ +/* + * Hex digit conversion functions. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/strcvt.h> + +char hex(int digit) +{ + if(digit < 10) + return '0' + digit; + else + return '7' + digit; +}; + +char *hexbyte(uchar v) +{ + static char h[3]; + + h[0] = hex(v / 16); + h[1] = hex(v % 16); + h[2] = 0; + return h; +}; + +char *hexshort(ushort v) +{ + static char h[5]; + + strcpy(h, hexbyte((uchar)(v / 256))); + strcpy(h + 2, hexbyte((uchar)(v % 256))); + return h; +}; + +char *hexlong(ulong v) +{ + static char h[9]; + + strcpy(h, hexshort((ushort)(v / 65536))); + strcpy(h + 4, hexshort((ushort)(v % 65536))); + return h; +}; diff --git a/sdk/other/isftype.c b/sdk/other/isftype.c new file mode 100644 index 0000000..bee42ca --- /dev/null +++ b/sdk/other/isftype.c @@ -0,0 +1,22 @@ +/* + * File type testing routine. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <std/files.h> + +bool isftype(const char *path, int ftype) +{ + struct stat ino; + + if(stat(path, &ino)) + return FALSE; + + if((ino.st_mode & S_IFMT) == ftype) + return TRUE; + + return FALSE; +} + diff --git a/sdk/other/make.conf b/sdk/other/make.conf new file mode 100644 index 0000000..e8b05bd --- /dev/null +++ b/sdk/other/make.conf @@ -0,0 +1,2 @@ +fn_find_file MEMORY_H_MISSING $inc/memory.h + diff --git a/sdk/other/memalloc.c b/sdk/other/memalloc.c new file mode 100644 index 0000000..6d31108 --- /dev/null +++ b/sdk/other/memalloc.c @@ -0,0 +1,35 @@ +/* + * Advanced memory pool allocation scheme. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse consult product license. + */ + +#include <other/memory.h> +#include <std/math.h> + +void *memalloc(MEMPOOL *mem, int len) +{ + _MEMFREE *free = mem->mem_free; + _MEMCELL *cell = NULL; + + len = align(len, __OBJALIGN); + + while(free) + { + if(free->size == len) + { + cell = free->list; + break; + } + free = free->next; + } + + if(cell) + { + free->list = cell->next; + return cell; + } + + return memreq(mem, len); +} diff --git a/sdk/other/memdup.c b/sdk/other/memdup.c new file mode 100644 index 0000000..af1f3cf --- /dev/null +++ b/sdk/other/memdup.c @@ -0,0 +1,22 @@ +/* + * Duplicate object into a memory pool. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <std/string.h> +#include <other/memory.h> + +void *memdup(void *obj, size_t size) +{ + void *new = (void *)malloc(size); + + if(!new) + return NULL; + + memcpy(new, obj, size); + return new; +} + + diff --git a/sdk/other/memfree.c b/sdk/other/memfree.c new file mode 100644 index 0000000..1939f14 --- /dev/null +++ b/sdk/other/memfree.c @@ -0,0 +1,38 @@ +/* + * Advanced free space deallocation for memory pools. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/memory.h> +#include <std/math.h> + +void memfree(MEMPOOL *mem, void *obj, int len) +{ + _MEMFREE *free = mem->mem_free; + _MEMCELL *cell = (_MEMCELL *)obj; + len = align(len, __OBJALIGN); + + while(free) + { + if(free->size == len) + break; + + free = free->next; + } + + if(!free) + { + free = memreq(mem, sizeof(_MEMFREE)); + free->list = NULL; + free->next = mem->mem_free; + mem->mem_free = free; + } + + if(free) + { + cell->next = free->list; + free->list = cell; + } +} diff --git a/sdk/other/memory.h b/sdk/other/memory.h new file mode 100644 index 0000000..902edd2 --- /dev/null +++ b/sdk/other/memory.h @@ -0,0 +1,103 @@ +/* + * Portable memory manipulation and management routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __OTHER_MEMORY_H__ +#define __OTHER_MEMORY_H__ + +#ifndef __STD_TYPES_H__ +#include <std/types.h> +#endif + +#ifndef MEMORY_H_MISSING +#include <memory.h> +#endif + +#ifndef __MEMALIGN +#define __MEMALIGN sizeof(ptr_t) +#endif + +#ifndef __OBJALIGN +#define __OBJALIGN __MEMALIGN +#endif + +struct _mempool; +struct _mempage; +struct _memfree; +struct _memcell; + +typedef struct _mempool +{ + int mem_psize; + int mem_pcount; + int mem_pused; + void *(*mem_pfault)(struct _mempool *mem, int reqsize); + struct _memfree *mem_free; + struct _mempage *mem_reuse; + struct _mempage *mem_last; +} MEMPOOL; + +typedef struct _mempage +{ + struct _mempage *page_next; + int page_used; + uchar page[ EMPTY ]; +} MEMPAGE; + +typedef struct _memfree +{ + struct _memfree *next; + struct _memcell *list; + int size; +} _MEMFREE; + +typedef struct _memcell +{ + void *next; +} _MEMCELL; + +#define memfault(mem, fault) mem->mem_pfault = fault; +#define memfirst(mem) ((MEMPAGE *)((char *)(mem) - sizeof(MEMPAGE))) + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __NAMESPACE +#define mempool __NAMESPACE(mempool) +#define memreuse __NAMESPACE(memreuse) +#define memrelease __NAMESPACE(memrelease) +#define memreq __NAMESPACE(memreq) +#define memlreq __NAMESPACE(memlreq) +#define strreq __NAMESPACE(strreq) +#define strlreq __NAMESPACE(strlreq) +#define memdup __NAMESPACE(memdup) +#define memalloc __NAMESPACE(memalloc) +#define memfree __NAMESPACE(memfree) +#endif + +MEMPOOL *mempool(int psize, int pcount); +void memreuse(MEMPOOL *mem); +void memrelease(MEMPOOL *mem); +void *memreq(MEMPOOL *mem, size_t memsize); +void *memlreq(MEMPOOL *mem, size_t memsize); +char *strreq(MEMPOOL *mem, const char *str); +char *strlreq(MEMPOOL *mem, const char *str); +void *memdup(void *, size_t); + +/* more advanced allocation schemes */ + +void *memalloc(MEMPOOL *mem, int memsize); +void memfree(MEMPOOL *mem, void *obj, int memsize); + +#ifdef __cplusplus +} +#endif + +#endif + + + diff --git a/sdk/other/mempool.c b/sdk/other/mempool.c new file mode 100644 index 0000000..ef27638 --- /dev/null +++ b/sdk/other/mempool.c @@ -0,0 +1,49 @@ +/* + * Memory pool creation. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/memory.h> +#include <std/files.h> +#include <std/math.h> +#include <std/process.h> + +static void *fault(MEMPOOL *mem, int request) +{ + fputs("* mempool: memory pool exhausted\n", stderr); + exit(EX_SOFTWARE); +} + +MEMPOOL *mempool(int psize, int pcount) +{ + char *page; + MEMPAGE *first; + MEMPOOL *pool; + + psize = align(psize, __MEMALIGN); + if(NULL == (page = (char *)malloc(psize))) + return NULL; + + first = (MEMPAGE *)page; + pool = (MEMPOOL *)(page + sizeof(MEMPAGE)); + + first->page_next = NULL; + first->page_used = sizeof(MEMPOOL); + + pool->mem_psize = psize - sizeof(MEMPAGE); + pool->mem_pcount = pcount; + pool->mem_pused = 1; + pool->mem_pfault = fault; + pool->mem_reuse = NULL; + pool->mem_last = first; + pool->mem_free = NULL; + return pool; +} + + + + + + diff --git a/sdk/other/memrelease.c b/sdk/other/memrelease.c new file mode 100644 index 0000000..144bff6 --- /dev/null +++ b/sdk/other/memrelease.c @@ -0,0 +1,43 @@ +/* + * Relallocate and release memory pools. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/memory.h> + +void memrelease(MEMPOOL *mem) +{ + MEMPAGE *page = memfirst(mem); + MEMPAGE *next; + + while(page) + { + next = page->page_next; + free(page); + page = next; + } +} + +void memreuse(MEMPOOL *mem) +{ + MEMPAGE *page = memfirst(mem); + MEMPAGE *next; + + page = page->page_next; + while(page) + { + next = page->page_next; + free(page); + page = next; + } + mem->mem_pused = 1; + mem->mem_free = NULL; + page = mem->mem_last = memfirst(mem); + page->page_used = 0; + page->page_next = NULL; +} + + + diff --git a/sdk/other/memreq.c b/sdk/other/memreq.c new file mode 100644 index 0000000..16f8433 --- /dev/null +++ b/sdk/other/memreq.c @@ -0,0 +1,59 @@ +/* + * Copy strings and objects into a memory pool. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/memory.h> +#include <std/math.h> + +static void *memrequest(MEMPOOL *mem, MEMPAGE *page, size_t len) +{ + int psize = mem->mem_psize; + void *obj; + + /* align objects to ptr field size */ + + len = align(len, __OBJALIGN); + + if(len > mem->mem_psize) + return (*mem->mem_pfault)(mem, len); + + while(page) + { + if(page->page_used + len <= psize) + { + obj = &page->page[page->page_used]; + page->page_used += len; + return obj; + } + page = page->page_next; + } + + if(mem->mem_pused >= mem->mem_pcount) + return (*mem->mem_pfault)(mem, len); + + ++mem->mem_pused; + page = (MEMPAGE *)malloc(psize + sizeof(MEMPAGE)); + if(!page) + return (*mem->mem_pfault)(mem, len); + + mem->mem_last->page_next = page; + mem->mem_last = page; + page->page_used = len; + page->page_next = NULL; + return page->page; +} + +void *memlreq(MEMPOOL *mem, size_t len) +{ + return memrequest(mem, mem->mem_last, len); +} + +void *memreq(MEMPOOL *mem, size_t len) +{ + return memrequest(mem, memfirst(mem), len); +} + + diff --git a/sdk/other/picture.c b/sdk/other/picture.c new file mode 100644 index 0000000..3ff2dba --- /dev/null +++ b/sdk/other/picture.c @@ -0,0 +1,112 @@ +/* + * String formatting of numeric data. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <std/string.h> + +char *picture(char *buf, const char *pict, long value) +{ + char *bp = buf, *tp; + long shift = 0; + int sign = 0; + int zfill = 0; + int digit; + int currency = 0; + int digits = 0; + + if(value < 0) + { + ++sign; + value = -value; + } + + while(*pict) + { + switch(*pict) + { + case '$': + ++currency; + *(bp++) = ' '; + ++pict; + break; + case '+': + if(sign) + *(bp++) = ' '; + else + *(bp++) = '+'; + ++pict; + break; + case '-': + if(sign) + *(bp++) = '-'; + else + *(bp++) = ' '; + ++pict; + break; + case '9': + case '0': + shift *= 10; + if(!shift) + shift = 1; + default: + *(bp++) = *(pict++); + } + } + if(value >= shift * 10) + { + bp = buf; + while(*bp) + { + if(isdigit(*bp)) + *bp = '#'; + ++bp; + } + return buf; + } + bp = tp = buf; + while(*bp) + { + switch(*bp) + { + case ',': + if(*(bp - 1) == '#') + { + *bp = '#'; + break; + } + if(!zfill) + *bp = ' '; + break; + case '#': + if(!digits) + if(shift > value) + break; + case '0': + ++zfill; + case '9': + ++digits; + digit = (int)(value / shift); + if((digit > 0) || (shift == 1)) + ++zfill; + if(!zfill && !digit) + digit = (int)(' ' - '0'); + *bp = (char)('0' + digit); + if(isdigit(*bp) && currency) + { + currency = 0; + *(tp - 1) = '$'; + } + value %= shift; + shift /= 10; + } + if(*bp != '#') + *(tp++) = *bp; + ++bp; + } + *tp = 0; + return buf; +} + diff --git a/sdk/other/search.c b/sdk/other/search.c new file mode 100644 index 0000000..15963bf --- /dev/null +++ b/sdk/other/search.c @@ -0,0 +1,46 @@ +/* + * File path search routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/files.h> +#include <other/string.h> +#include <std/process.h> + +#ifdef QNX +#define PATHMARK "!" +#endif + +#ifndef PATHMARK +#define PATHMARK ":" +#endif + +char *search(const char *path, const char *file) +{ + static char buf[PATH_MAX + 1]; + char pbuf[PATH_MAX + 1]; + char *p; + + if(!path) + return NULL; + + strcpy(pbuf, path); + + p = strtok(pbuf, PATHMARK); + + while(p) + { + if(*p) + fncat(strcpy(buf, p), file); + else + strcpy(buf, file); + if(isfile(buf)) + return buf; + p = strtok(NULL, PATHMARK); + } + return NULL; +} + + diff --git a/sdk/other/strblank.c b/sdk/other/strblank.c new file mode 100644 index 0000000..d3e8d18 --- /dev/null +++ b/sdk/other/strblank.c @@ -0,0 +1,24 @@ +/* + * Test for blank strings. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> + +char __SPACES[] = " \t\r\n"; + +bool strblank(const char *str) +{ + if(!str) + return TRUE; + + while(*str) + { + if(!strchr(__SPACES, *str)) + return FALSE; + ++str; + } + return TRUE; +} diff --git a/sdk/other/strcopy.c b/sdk/other/strcopy.c new file mode 100644 index 0000000..077f897 --- /dev/null +++ b/sdk/other/strcopy.c @@ -0,0 +1,61 @@ +/* + * String copying defined for supporting over-lapping strings 'insertion'. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> + +static char *revcopy(char *to, const char *from, size_t count) +{ + while(count--) + *(to--) = *(from--); + + *to = *from; + return to; +}; + +char *strcopy(char *to, const char *from) +{ + char *s1 = to; + int l = from - to; + int l2 = len(from); + + if(!to || !from) + return NULL; + + if(l > 0 && l <= l2) + return revcopy(to + l2, from + l2, l2); + + ++l2; + while(l2--) + *(to++) = *(from++); + + return s1; +}; + +char *strncopy(char *to, const char *from, int l2) +{ + char *s1 = to; + int l = from - to; + if(len(from) < l2) + return strcopy(to, from); + + if(!to || !from) + return NULL; + + if(l > 0 && l <= l2) + { + to[l2] = 0; + --l2; + return revcopy(to + l2, from + l2, l2); + } + + while(l2--) + *(to++) = *(from++); + + *to = 0; + return s1; +}; + diff --git a/sdk/other/strcvt.h b/sdk/other/strcvt.h new file mode 100644 index 0000000..443c820 --- /dev/null +++ b/sdk/other/strcvt.h @@ -0,0 +1,56 @@ +/* + * Portable string handling routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __OTHER_STRCVT_H__ +#define __OTHER_STRCVT_H__ + +#ifndef __STD_STRING_H__ +#include <std/string.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __NAMESPACE +#define __SPACES __NAMESPACE(__SPACES) +#endif + +extern char __SPACES[]; + +#ifdef __NAMESPACE +#define atob __NAMESPACE(atob) +#define strint __NAMESPACE(strint) +#define picture __NAMESPACE(picture) +#define expand __NAMESPACE(expand) +#define xdigit __NAMESPACE(xdigit) +#define xtol __NAMESPACE(xtol) +#define hex __NAMESPACE(hex) +#define hexbyte __NAMESPACE(hexbyte) +#define hexshort __NAMESPACE(hexshort) +#define hexlong __NAMESPACE(hexlong) +#define str2bcd __NAMESPACE(str2bcd) +#define bcd2str __NAMESPACE(bcd2str) +#endif + +bool atob(const char *str); +char *strint(long i, int z); +char *picture(char *buf, const char *pict, long value); +char *expand(const char *str); +int xdigit(char digit); +ulong xtol(const char *digit); +char hex(int value); +char *hexbyte(uchar); +char *hexshort(ushort); +char *hexlong(ulong); +char *str2bcd(uchar *bcd, char *str, int max); +uchar *bcd2str(char *str, uchar *bcd, int len); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/other/strdiff.c b/sdk/other/strdiff.c new file mode 100644 index 0000000..a0297f6 --- /dev/null +++ b/sdk/other/strdiff.c @@ -0,0 +1,24 @@ +/* + * Often used to evaluate similarity of soundex codes. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> +#include <std/math.h> + +int strdiff(const char *s1, const char *s2) +{ + int l1 = len(s1); + int l2 = len(s2); + int l = min(l1, l2); + int dif = abs(l1 - l2); + + while(l--) + { + if(*(s1++) != *(s2++)) + ++dif; + } + return dif; +} diff --git a/sdk/other/string.h b/sdk/other/string.h new file mode 100644 index 0000000..5db8cd4 --- /dev/null +++ b/sdk/other/string.h @@ -0,0 +1,65 @@ +/* + * Portable string handling routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __OTHER_STRINGS_H__ +#define __OTHER_STRINGS_H__ + +#ifndef __STD_STRING_H__ +#include <std/string.h> +#endif + +#ifndef __STD_TYPES_H__ +#include <std/types.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __NAMESPACE +#define __SPACES __NAMESPACE(__SPACES) +#endif + +extern char __SPACES[]; + +#ifdef __NAMESPACE +#define strblank __NAMESPACE(strblank) +#define strtrim __NAMESPACE(strtrim) +#define strrtrim __NAMESPACE(strrtrim) +#define strltrim __NAMESPACE(strltrim) +#define right __NAMESPACE(right) +#define left __NAMESPACE(left) +#define ccount __NAMESPACE(ccount) +#define tail __NAMESPACE(tail) +#define field __NAMESPACE(field) +#define token __NAMESPACE(token) +#define strcopy __NAMESPACE(strcopy) +#define strncopy __NAMESPACE(strncopy) +#define strdiff __NAMESPACE(strdiff) +#define getargv __NAMESPACE(getargv) +#endif + +bool strblank(const char *str); +char *strtrim(char *s, const char *trim); +char *strrtrim(char *s, const char *trim); +char *strltrim(char *s, const char *trim); +char *right(char *str, size_t len); +char *left(char *str, size_t len); +int ccount(const char *str, const char *list); +char *tail(const char *str); +char *field(char **ptr, const char *tok); +char *token(char **ptr, const char *tok); +char *strcopy(char *to, const char *from); +char *strncopy(char *to, const char *from, int len); +int strdiff(const char *s1, const char *s2); +int getargv(char *base[], char *str); +void fatal(int exitcode, const char *format, ...); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/other/strint.c b/sdk/other/strint.c new file mode 100644 index 0000000..f4291a1 --- /dev/null +++ b/sdk/other/strint.c @@ -0,0 +1,51 @@ +/* + * Convert integer to string, with optional leading zeros. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/strcvt.h> + +char *strint(long i, int z) +{ + static char buf[30]; + char b1[30]; + char *p = buf, *q = b1; + unsigned u; + + if(!i) + { + if(z < 1) + z = 1; + while(z--) + *(p++) = '0'; + *p = 0; + return buf; + } + if((i < 0) && !z) + { + i = -i; + buf[0] = '-'; + ++p; + } + u = (unsigned)i; + + while(u > 0) + { + *(q++) = (char)(u % 10) + '0'; + u /= 10; + } + *q = 0; + z -= strlen(b1); + while(z-- > 0) + *(p++) = '0'; + + while(q > b1) + *(p++) = *(--q); + *p = 0; + return buf; +} + + + diff --git a/sdk/other/strpos.c b/sdk/other/strpos.c new file mode 100644 index 0000000..79afbf5 --- /dev/null +++ b/sdk/other/strpos.c @@ -0,0 +1,46 @@ +/* + * String pointer manipulation routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> + +char *tail(const char *tail) +{ + if(!tail) + return NULL; + + while(*tail) + ++tail; + + return (char *)tail; +} + +char *left(char *str, size_t pos) +{ + if(!str) + return NULL; + + if(pos < strlen(str)) + str[pos] = 0; + + return str; +}; + +char *right(char *s, size_t l) +{ + size_t len; + + if(!s) + return NULL; + + len = strlen(s); + if(len <= l) + return s; + + return s + len - l; +} + + diff --git a/sdk/other/strreq.c b/sdk/other/strreq.c new file mode 100644 index 0000000..fb69b95 --- /dev/null +++ b/sdk/other/strreq.c @@ -0,0 +1,39 @@ +/* + * Memory pool string copy. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/memory.h> + +char *strreq(MEMPOOL *mem, const char *str) +{ + char *newstr; + + if(!str) + return NULL; + + newstr = memreq(mem, strlen(str) + 1); + if(!newstr) + return NULL; + + strcpy(newstr, str); + return newstr; +} + +char *strlreq(MEMPOOL *mem, const char *str) +{ + char *newstr; + + if(!str) + return NULL; + + newstr = memlreq(mem, strlen(str) + 1); + if(!newstr) + return NULL; + + strcpy(newstr, str); + return newstr; +} + diff --git a/sdk/other/strtrim.c b/sdk/other/strtrim.c new file mode 100644 index 0000000..9afcfd5 --- /dev/null +++ b/sdk/other/strtrim.c @@ -0,0 +1,45 @@ +/* + * Portable string trimming routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> + +char *strtrim(char *str, const char *trim) +{ + return strltrim(strrtrim(str, trim), trim); +} + +char *strrtrim(char *str, const char *trim) +{ + char *end; + + if(!str) + return NULL; + + end = str + strlen(str); + + while(end-- > str) + { + if(!strchr(trim, *end)) + return str; + *end = 0; + } + return str; +} + +char *strltrim(char *str, const char *trim) +{ + if(!str) + return NULL; + + while(*str) + { + if(!strchr(trim, *str)) + return str; + ++str; + } + return str; +} diff --git a/sdk/other/token.c b/sdk/other/token.c new file mode 100644 index 0000000..c9846ed --- /dev/null +++ b/sdk/other/token.c @@ -0,0 +1,50 @@ +/* + * Alternate thread-safe string token parsing. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> + +char *token(char **ptr, const char *tok) +{ + char *p; + char *brk; + + if(strblank(*ptr)) + return NULL; + + p = strltrim(*ptr, tok); + brk = strpbrk(p, tok); + if(brk) + { + *brk = 0; + *ptr = strltrim(++brk, tok); + if(!(**ptr)) + *ptr = NULL; + } + else + *ptr = NULL; + return p; +} + +char *field(char **ptr, const char *tok) +{ + char *p = *ptr; + char *brk; + + if(strblank(p)) + return NULL; + + brk = strpbrk(p, tok); + if(brk) + { + *brk = 0; + *ptr = ++brk; + } + else + *ptr = NULL; + + return p; +} diff --git a/sdk/other/xval.c b/sdk/other/xval.c new file mode 100644 index 0000000..c7d1276 --- /dev/null +++ b/sdk/other/xval.c @@ -0,0 +1,28 @@ +/* + * Hex digit conversions. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/strcvt.h> + +int xdigit(char c) +{ + if(c > '9') + return upper(c) - '7'; + + return digit(c); +}; + +ulong xtol(const char *s) +{ + ulong v = 0l; + + while(isxdigit(*s)) + { + v = v << 4 | xdigit(*s); + ++s; + } + return v; +}; diff --git a/sdk/proc/Makefile.in b/sdk/proc/Makefile.in new file mode 100644 index 0000000..94ae3cb --- /dev/null +++ b/sdk/proc/Makefile.in @@ -0,0 +1,18 @@ +# +# Template to build our "other" object modules(libother.a) +# $Id: Makefile.in 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $ +# Copyright (c) 1997 by Tycho Softworks. +# + +OBJS = spawn.o pdetach.o priority.o + +.c.o: + $(CC) $(CFLAGS) $(OPTIMIZE) -I.. -o $@ -c $< + $(AR) r ../lib/libproc.a $@ + +all: $(OBJS) + ranlib ../lib/libproc.a + +clean: + rm *.o + diff --git a/sdk/proc/bind.conf b/sdk/proc/bind.conf new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/sdk/proc/bind.conf @@ -0,0 +1 @@ + diff --git a/sdk/proc/make.conf b/sdk/proc/make.conf new file mode 100644 index 0000000..2ce0aaa --- /dev/null +++ b/sdk/proc/make.conf @@ -0,0 +1,5 @@ +inc=$CONFIG_HOST/include + +fn_find_file SYS_RESOURCE_H_MISSING $inc/sys/resource.h +fn_find_type SETPRIORITY_F_MISSING setpriority $inc/sys/resource.h + diff --git a/sdk/proc/pdetach.c b/sdk/proc/pdetach.c new file mode 100644 index 0000000..40814e4 --- /dev/null +++ b/sdk/proc/pdetach.c @@ -0,0 +1,78 @@ +/* + * Deamon-ify a user process; detach from controlling terminal and parent. + * $Id: daemon.c 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions on distribution and reuse see product license. + * + * Abstract: + * Daemon processes are commonly used in UNIX to build server + * applications. This module captures the essense of functionality + * required to make a process into a daemon within a single function + * call. + * + * Functions: + * daemon() - convert user process into a daemon. + */ + +#include <proc/process.h> +#include <std/signal.h> + +/* Daemonify a user process under UNIX. + * + * Abstract: + * In UNIX, a user process becomes a daemon by detaching itself from + * it's parent process and establishes it's own process group. A + * daemon may also detach itself from it's controlling terminal. + * This is usually accomplished through fork(). + * + * Paramaters: + * flag - specifies daemon mode of operation: + * D_KEEPALL keeps all files open. + * D_KEEPSTDIO keeps stdio (stdin, stdout, stderr) open. + * D_KEEPNONIO detaches from stdio, keeps other files. + * D_KEEPNONE closes all open files. + * + * Returns: + * New pid of user process running as a daemon. + * + * Exceptions: + * Any failure terminates the process. No error message is possible + * since the process may already be detached from user I/O. + */ + +pid_t pdetach(int flag) +{ + pid_t pid; + int max = OPEN_MAX; + int i; + + signal(SIGHUP, SIG_IGN); + + i = 0; + if(flag == D_KEEPSTDIO) + i = 3; + + if(flag == D_KEEPNONIO) + max = 3; + + while((i < max) && (flag != D_KEEPALL)) + close(i++); + + pid = fork(); + if(pid < 0) + return pid; + + if(pid > 0) + exit(EX_OK); + + setsid(); + setpgid(0, getpid()); + pid = fork(); + if(pid < 0) + return pid; + + if(pid > 0) + exit(EX_OK); + + return getpid(); +} diff --git a/sdk/proc/priority.c b/sdk/proc/priority.c new file mode 100644 index 0000000..8818567 --- /dev/null +++ b/sdk/proc/priority.c @@ -0,0 +1,73 @@ +/* + * Specify process for soft realtime scheduling treatment. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <proc/process.h> +#include <std/time.h> + +#ifndef SYS_RESOURCE_H_MISSING +#include <sys/resource.h> +#endif + +#ifndef SETPRIORITY_F_MISSING + +int priority(int pri) +{ +#ifdef _POSIX_PRIORITY_SCHEDULING + #define _P __P + + #include <sched.h> + + struct sched_param p; +#endif + int newpri = getpriority(PRIO_PROCESS, 0) - pri - 1; + + if(setpriority(PRIO_PROCESS, 0, newpri)) + return -1; + +#ifdef _POSIX_MEMLOCK + #include <linux/mman.h> + + if(mlockall(MCL_CURRENT | MCL_FUTURE)) + return -1; +#endif + +#ifdef _POSIX_PRIORITY_SCHEDULING + if(pri > 0) + { + p.sched_priority = sched_get_priority_min(SCHED_RR) + pri - 1; + if(sched_setscheduler(0, SCHED_RR, &p)) + return -1; + } +#endif + + return 0; +} + +#else + +int priority(int priority) +{ + return nice(- priority - 1); +} +#endif + +#ifdef _POSIX_PRIORITY_SCHEDULING +#include <sched.h> + +void yield(void) +{ + sched_yield(); +} +#else + +void yield(void) +{ + sleep(0); +} +#endif + + diff --git a/sdk/proc/process.h b/sdk/proc/process.h new file mode 100644 index 0000000..d65b765 --- /dev/null +++ b/sdk/proc/process.h @@ -0,0 +1,57 @@ +/* + * Portable process handling routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __PROC_PROCESS_H__ +#define __PROC_PROCESS_H__ + +#ifndef __STD_PROCESS_H__ +#include <std/process.h> +#endif + +/* Spawn services under UNIX fork() */ + +#define P_NOWAIT 0x00 /* Default, run concurrent */ +#define P_WAIT 0x01 /* Wait for and return exit status */ +#define P_BACKGROUND 0x02 /* Detach child from our stdio */ +#define P_SESSION 0x04 /* Use setsid() on child */ +#define P_OVERLAY 0x08 /* Really 'exec' called via spawn */ + +/* Some common/portable spawn varients and masks */ + +#define P_DETACH P_NOWAIT | P_SESSION | P_BACKGROUND +#define P_NOWAITO P_NOWAIT | P_SESSION + +/* Daemon initialization options */ + +#define D_KEEPSTDIO 0 /* Daemon keeps stdio connection */ +#define D_KEEPALL 1 /* Daemon keeps all open files */ +#define D_KEEPNONIO 2 /* Detach from stdio, keep others open */ +#define D_KEEPNONE 3 /* Deamon closes all files */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Common process invokation services using fork() */ + +#ifdef __NAMESPACE +#define spawnv __NAMESPACE(spawnv) +#define spawnvp __NAMESPACE(spawnvp) +#define pdetach __NAMESPACE(pdetach) +#define priority __NAMEPSACE(priority) +#endif + +int spawnv(const int P_mode, const char *path, char *const argv[]); +int spawnvp(const int P_mode, const char *path, char *const argv[]); +pid_t pdetach(const int D_flag); /* Make current process a daemon */ +int priority(int pri); /* set realtime priorities */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/proc/spawn.c b/sdk/proc/spawn.c new file mode 100644 index 0000000..2b6d7db --- /dev/null +++ b/sdk/proc/spawn.c @@ -0,0 +1,92 @@ +/* + * Spawn services built on fork() for those libc's that lack spawning. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <proc/process.h> +#include <std/files.h> + +static void spawn_redirect(int io, int mode) +{ + int fd = open("/dev/null", mode); + + if(fd < 0) + exit(EX_OSFILE); + + if(fd != io) + { + dup2(fd, io); + close(fd); + } +} + +static int spawn_wait(pid_t pid, int mode) +{ + int waitflag = mode & P_WAIT; + + /* -1 on fork failure */ + + if(pid == -1) + return -1; + + if(!waitflag) + return pid; + + waitpid(pid, &waitflag, 0); + return WEXITSTATUS(waitflag); +} + +static void spawn_mode(int mode) +{ + int i; + + if(mode & P_BACKGROUND) + { + spawn_redirect(0, O_RDONLY); + spawn_redirect(1, O_WRONLY); + spawn_redirect(2, O_WRONLY); + } + + for(i = 3; i < OPEN_MAX; ++i) + close(i); + + if(mode & P_SESSION) + setsid(); +} + +int spawnv(const int mode, const char *path, char *const argv[]) +{ + pid_t pid = 0; + int status; + + if(!(mode & P_OVERLAY)) + pid = fork(); + + if(pid) + return spawn_wait(pid, mode); + + spawn_mode(mode); + execv(path, argv); + exit(EX_UNAVAILABLE); + return -1; +} + +int spawnvp(const int mode, const char *path, char *const argv[]) +{ + pid_t pid = 0; + int status; + + if(!(mode & P_OVERLAY)) + pid = fork(); + + if(pid) + return spawn_wait(pid, mode); + + spawn_mode(mode); + execvp(path, argv); + exit(EX_UNAVAILABLE); + return -1; +} + diff --git a/sdk/std/Makefile.in b/sdk/std/Makefile.in new file mode 100644 index 0000000..d8f600b --- /dev/null +++ b/sdk/std/Makefile.in @@ -0,0 +1,18 @@ +# +# Template to build standard sdk object modules(libstd.a) +# $Id: Makefile.in 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $ +# Copyright (c) 1997 by Tycho Softworks. +# + +OBJS = string.o utmp.o + +.c.o: + $(CC) $(CFLAGS) $(OPTIMIZE) -I.. -o $@ -c $< + $(AR) r ../lib/libstd.a $@ + +all: $(OBJS) + ranlib ../lib/libstd.a + +clean: + rm *.o + diff --git a/sdk/std/bind.conf b/sdk/std/bind.conf new file mode 100644 index 0000000..65ee123 --- /dev/null +++ b/sdk/std/bind.conf @@ -0,0 +1,69 @@ +BIND_OPTS=$BIND_OPTS' cc optimize cflags arch' +OPTIMIZE='' +CFLAGS='' + +if test -z "$CONFIG_CC" ; then + + echo -n "Analyzing C Compiler..." + + if test -z "$CONFIG_ARCH" ; then + CONFIG_ARCH=`uname -m`"-"`uname` + fi + + if fn_find_fpath -x gcc $PATH ; then + CONFIG_CC='gcc' + echo "gcc" + else + if test -z "$CONFIG_CC" ; then + CONFIG_CC='cc' + echo 'cc' + fi + fi +fi + +opt_optimize() { + OPTIMIZE="$1" + CONFIG_COPT="$1" + return 0 +} + +opt_cflags() { + CONFIG_ENDIAN="" + CONFIG_CFLAGS="$1" + CFLAGS="$1" +} + +opt_cc() { + CONFIG_CC="$1" + CONFIG_COPT="$OPTIMIZE" + CONFIG_CFLAGS="$CFLAGS" + return 0 +} + +opt_arch() { + CONFIG_ENDIAN="" + CONFIG_ARCH="$1" + if test "gcc" = $CONFIG_CC ; then + CONFIG_COPT="$OPTIMIZE" + if test -d /usr/local/lib/gcc-lib ; then + GCC_LIB='/usr/local/lib/gcc-lib' + fi + if test -d /usr/lib/gcc-lib ; then + GCC_LIB='/usr/lib/gcc-lib' + fi + if fn_find_fpath -d "$1" "$GCC_LIB"':/usr:/usr/local' ; then + CONFIG_CFLAGS='-b '"$1" + else + echo "config: $1: unsupported gcc architecture" + exit -1 + fi + if -d /usr/$1/include ; then + CONFIG_HOST=/usr/$1 + fi + if -d /usr/local/$1/include ; then + CONFIG_HOST=/usr/local/$1 + fi + fi + return 0 +} + diff --git a/sdk/std/files.h b/sdk/std/files.h new file mode 100644 index 0000000..84ad33a --- /dev/null +++ b/sdk/std/files.h @@ -0,0 +1,47 @@ +/* + * Portable support for file manipulation and access related functions. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __STD_FILES_H__ +#define __STD_FILES_H__ + +#ifndef __STD_TYPES_H__ +#include <std/types.h> +#endif + +#include <stdio.h> +#include <sys/stat.h> + +#ifndef UNISTD_H_MISSING +#include <unistd.h> +#endif + +#ifndef SYS_FCNTL_H_MISSING +#include <sys/fcntl.h> +#else +#ifndef FCNTL_H_MISSING +#include <fcntl.h> +#endif +#endif + +#ifndef IO_H_MISSING +#include <io.h> +#endif + +#ifndef __STD_TYPES_H__ +#include <std/types.h> +#endif + + +#ifdef OFF_T_MISSING +typedef long off_t; +#endif + +#ifdef FD_T_MISSING +typedef int fd_t; +#endif + +#endif diff --git a/sdk/std/help.conf b/sdk/std/help.conf new file mode 100644 index 0000000..71dfb97 --- /dev/null +++ b/sdk/std/help.conf @@ -0,0 +1,4 @@ +--arch= Compiler Architecture / Cross-Compile +--cc= Specify C Compiler to use +--cflags= Specify Compiler Options +--optimize= Specify Compiler Optimizations diff --git a/sdk/std/limits.h b/sdk/std/limits.h new file mode 100644 index 0000000..0766fe3 --- /dev/null +++ b/sdk/std/limits.h @@ -0,0 +1,97 @@ +/* + * Portable re-definition of limits header file. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __STD_LIMITS_H__ +#define __STD_LIMITS_H__ + +#include <limits.h> + +#ifndef __CONFIG_H__ +#include <config.h> +#endif + +#ifndef POSIX1_LIM_H_MISSING +#include <posix1_lim.h> +#else +#ifndef UNISTD_H_MISSING +#include <unistd.h> +#endif +#include <std/posix1_lim.h> +#endif + +#ifndef NR_OPEN +#ifdef OPEN_MAX +#define NR_OPEN OPEN_MAX +#else +#define NR_OPEN _POSIX_OPEN_MAX +#endif +#endif + +#ifndef NGROUPS_MAX +#define NGROUPS_MAX _POSIX_NGROUPS_MAX +#endif + +#ifndef CHILD_MAX +#define CHILD_MAX _POSIX_CHILD_MAX +#endif + +#ifndef ARG_MAX +#define ARG_MAX _POSIX_ARG_MAX +#endif + +#ifndef LINK_MAX +#define LINK_MAX _POSIX_LINK_MAX +#endif + +#ifndef MAX_CANON +#define MAX_CANON _POSIX_MAX_CANON +#endif + +#ifndef MAX_INPUT +#define MAX_INPUT _POSIX_MAX_INPUT +#endif + +#ifndef NAME_MAX +#define NAME_MAX _POSIX_NAME_MAX +#endif + +#ifndef PATH_MAX +#define PATH_MAX _POSIX_PATH_MAX +#endif + +#ifndef PIPE_BUF +#define PIPE_BUF _POSIX_PIPE_BUF +#endif + +#ifndef SSIZE_MAX +#define SSIZE_MAX INT_MAX +#endif + +#ifndef STREAM_MAX +#define STREAM_MAX OPEN_MAX +#endif + +#ifndef TZONE_MAX +#define TZONE_MAX _POSIX_TZONE_MAX +#endif + +#ifdef MSDOS +#if !defined(GNU) && !defined(__386__) +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +#define MEM_SEGMENT_MAX 16 +#endif +#if defined(M_I86SM) || defined(M_I86MM)) +#define MEM_SEGMENT_MAX 16 +#endif +#endif +#endif + +#ifndef MEM_SEGMENT_MAX +#define MEM_SEGMENT_MAX 32 +#endif + +#endif diff --git a/sdk/std/make.conf b/sdk/std/make.conf new file mode 100644 index 0000000..bf20113 --- /dev/null +++ b/sdk/std/make.conf @@ -0,0 +1,102 @@ +if test "$CONFIG_CC" = gcc ; then + + CONFIG_FPIC='-fpic' + CONFIG_EMPTY="0" + if test -z "$CONFIG_GCC_GFLAG" ; then + echo 'void f(){}' >conftest.c + if gcc -g -c conftest.c 2>&1 >/dev/null ; then + CONFIG_CFLAGS='-g '$CONFIG_CFLAGS + CONFIG_GCC_GFLAG='yes' + else + CONFIG_GCC_GFLAG='no' + fi + fi + if test -z "$CONFIG_COPT" ; then + case "$CONFIG_ARCH" in + i486* | i586* | i686*) + CONFIG_COPT='-O2 -m486' + ;; + *) + CONFIG_COPT='-O2' + esac + fi +else + CONFIG_FPIC='' + CONFIG_EMPTY="" + if test -z "$CONFIG_CFLAGS" ; then + case "$CONFIG_ARCH" in + *-SCO_SV) + CONFIG_CFLAGS='-b elf' + CONFIG_COPT='-O3' + CONFIG_FPIC='-KPIC' + ;; + esac + fi + + if test -z "$CONFIG_COPT" ; then + CONFIG_COPT='-O' + fi +fi + +echo "#define EMPTY "$CONFIG_EMPTY >>$CONFIG + +echo "CC="$CONFIG_CC >>config.make +echo "CFLAGS="$CONFIG_CFLAGS >>config.make +echo "PICFLAG="$CONFIG_FPIC >>config.make +echo "OPTIMIZE="$CONFIG_COPT >>config.make + +inc=$CONFIG_HOST/include +typelist=`find $inc -name types.h -follow -print` + +echo 'CONFIG_CC="'$CONFIG_CC'"' >>config.cache +echo 'CONFIG_COPT="'$CONFIG_COPT'"' >>config.cache +echo 'CONFIG_ARCH="'$CONFIG_ARCH'"' >>config.cache +echo 'CONFIG_CFLAGS="'$CONFIG_CFLAGS'"' >>config.cache +echo 'CONFIG_PICFLAG="'$CONFIG_FPIC'"' >>config.cache +echo 'CONFIG_GCC_GFLAG="'$CONFIG_GCC_GFLAG'"' >>config.cache +echo 'CONFIG_HOST="'$CONFIG_HOST'"' >>config.cache + +fn_find_type UCHAR_T_MISSING "uchar;" $typelist +fn_find_type USHORT_T_MISSING "ushort;" $typelist +fn_find_type ULONG_T_MISSING "ulong;" $typelist +fn_find_type SIZE_T_MISSING "size_t;" $typelist +fn_find_type SSIZE_T_MISSING "ssize_t;" $typelist +fn_find_type PID_T_MISSING "pid_t;" $typelist $inc/unistd.h +fn_find_type OFF_T_MISSING "off_t;" $typelist $inc/stdio.h $inc/fcntl.h $inc/sys/fcntl.h $inc/io.h +fn_find_type FD_T_MISSING "fd_t;" $typelist:$inc/stdio.h + +if fn_find_type GNUSTRING_F_MISSING "strcasecmp" $inc/string.h ; then + fn_find_type STRICMP_F_MISSING "stricmp" $inc/string.h +fi + +fn_find_type STRLWR_F_MISSING "strlwr" $inc/string.h +fn_find_type STRDUP_F_MISSING "strdup" $inc/string.h +fn_find_type STRISTR_F_MISSING "stristr" $inc/string.h +fn_find_type SELECT_F_MISSING "select" $inc/select.h $inc/sys/select.h $inc/sys/time.h +fn_find_type GETUTENT_F_MISSING "getutent" $inc/utmp.h + +fn_find_type UT_USER_I_MISSING "ut_user" $inc/utmp.h + +fn_find_file POSIX1_LIM_H_MISSING $inc/posix1_lim.h +fn_find_file PROCESS_H_MISSING $inc/process.h +fn_find_file UNISTD_H_MISSING $inc/unistd.h +fn_find_file POSIX2_LIM_H_MISSING $inc/posix2_lim.h +fn_find_file SYS_SELECT_H_MISSING $inc/sys/select.h +fn_find_file SELECT_H_MISSING $inc/select.h +fn_find_file POLL_H_MISSING $inc/poll.h +fn_find_file SYS_POLL_H_MISSING $inc/sys/poll.h + +if fn_find_file WAIT_H_MISSING $inc/wait.h ; then + fn_find_file SYS_WAIT_H_MISSING $inc/sys/wait.h +fi +fn_find_file POSIX_OPT_H_MISSING $inc/posix_opt.h +fn_find_file CONFNAME_H_MISSING $inc/confname.h +fn_find_file SYSCONF_H_MISSING $inc/sysconf.h +fn_find_file ENV_H_MISSING $inc/env.h +fn_find_file SYSEXITS_H_MISSING $inc/sysexits.h +fn_find_file SYS_TIME_H_MISSING $inc/sys/time.h +if fn_find_file SYS_FCNTL_H_MISSING $inc/sys/fcntl.h ; then + fn_find_file FCNTL_H_MISSING $inc/fcntl.h +fi +fn_find_file IO_H_MISSING $inc/io.h + diff --git a/sdk/std/math.h b/sdk/std/math.h new file mode 100644 index 0000000..d1eb298 --- /dev/null +++ b/sdk/std/math.h @@ -0,0 +1,31 @@ +/* + * Common math functions and macros. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __STD_MATH_H__ +#define __STD_MATH_H__ + +#ifndef __STD_TYPES_H__ +#include <std/types.h> +#endif + +#ifndef min +#define min(a, b) ((a)<(b)?(a):(b)) +#endif + +#ifndef max +#define max(a, b) ((a)>(b)?(a):(b)) +#endif + +#ifndef abs +#define abs(a) ((a)<0?(-a):(a)) +#endif + +#ifndef align +#define align(x, s) ((((x) + (s) - 1) / (s)) *(s)) +#endif + +#endif diff --git a/sdk/std/poll.h b/sdk/std/poll.h new file mode 100644 index 0000000..a9eb3f9 --- /dev/null +++ b/sdk/std/poll.h @@ -0,0 +1,21 @@ +/* + * Find or insert replacement "poll" routine. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and use see product license. + */ + +#ifndef __STD_POLL_H__ +#define __STD_POLL_H__ + +#ifdef POLL_H_MISSING +#ifndef SYS_POLL_H_MISSING +#include <sys/poll.h> +#endif +#else +#include <poll.h> +#endif + +#include <std/time.h> + +#endif diff --git a/sdk/std/posix1_lim.h b/sdk/std/posix1_lim.h new file mode 100644 index 0000000..5520f22 --- /dev/null +++ b/sdk/std/posix1_lim.h @@ -0,0 +1,92 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* + * POSIX Standard: 2.9.2 Minimum Values Added to <limits.h> + */ + +#ifndef _POSIX1_LIMITS_H + +#define _POSIX1_LIMITS_H 1 + + +/* These are the standard-mandated minimum values. */ + +/* Maximum length of arguments to `execve', including environment. */ +#define _POSIX_ARG_MAX 4096 + +/* Maximum simultaneous processes per real user ID. */ +#define _POSIX_CHILD_MAX 6 + +/* Maximum link count of a file. */ +#define _POSIX_LINK_MAX 8 + +/* Number of bytes in a terminal canonical input queue. */ +#define _POSIX_MAX_CANON 255 + +/* Number of bytes for which space will be + available in a terminal input queue. */ +#define _POSIX_MAX_INPUT 255 + +/* Number of simultaneous supplementary group IDs per process. */ +#define _POSIX_NGROUPS_MAX 0 + +/* Number of files one process can have open at once. */ +#define _POSIX_OPEN_MAX 16 + +/* Number of bytes in a filename. */ +#define _POSIX_NAME_MAX 14 + +/* Number of bytes in a pathname. */ +#define _POSIX_PATH_MAX 255 + +/* Number of bytes than can be written atomically to a pipe. */ +#define _POSIX_PIPE_BUF 512 + +/* Largest value of a `ssize_t'. */ +#define _POSIX_SSIZE_MAX 32767 + +/* Number of streams a process can have open at once. */ +#define _POSIX_STREAM_MAX 8 + +/* Number of bytes in `tzname'. */ +#define _POSIX_TZNAME_MAX 3 + + +/* don't even think about changing it without checking tzfile.h + * in source code dir ./time first. + */ +#undef TZNAME_MAX +#define TZNAME_MAX 50 + +#ifndef SSIZE_MAX +#define SSIZE_MAX INT_MAX +#endif + +#ifndef STREAM_MAX +#define STREAM_MAX OPEN_MAX +#endif + +/* This value is a guaranteed minimum maximum. + The current maximum can be got from `sysconf'. */ + +#ifndef NGROUPS_MAX +#define NGROUPS_MAX _POSIX_NGROUPS_MAX +#endif + +#endif /* posix1_limits.h */ diff --git a/sdk/std/process.h b/sdk/std/process.h new file mode 100644 index 0000000..2fdf6ae --- /dev/null +++ b/sdk/std/process.h @@ -0,0 +1,99 @@ +/* + * Portable process handling routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __STD_PROCESS_H__ +#define __STD_PROCESS_H__ + +#ifndef __STD_TYPES_H__ +#include <std/types.h> +#endif + +#ifndef __STD_LIMITS_H__ +#include <std/limits.h> +#endif + +#ifndef POSIX2_LIM_H_MISSING +#include <posix2_lim.h> +#endif + +#ifndef POSIX_OPT_H_MISSING +#include <posix_opt.h> +#endif + +#ifndef UNISTD_H_MISSING +#include <unistd.h> +#endif + +#ifndef _SC_OPEN_MAX +#ifndef CONFNAME_H_MISSING +#include <confname.h> +#else +#ifndef SYSCONF_H_MISSING +#include <sysconf.h> +#endif +#endif +#endif + +#ifndef PROCESS_H_MISSING +#include <process.h> +#endif + +#ifndef WAIT_H_MISSING +#include <wait.h> +#else +#ifndef SYS_WAIT_H_MISSING +#include <sys/wait.h> +#endif +#endif + +#ifndef ENV_H_MISSING +#include <env.h> +#endif + +#ifndef SYSEXITS_H_MISSING +#include <sysexits.h> +#else +#include <std/sysexits.h> +#endif + +/* We now re-evaluate system limits using runtime sysconf() values */ + +#ifdef _SC_ARG_MAX +#undef ARG_MAX +#define ARG_MAX (sysconf(_SC_ARG_MAX)) +#endif + +#ifdef _SC_CHILD_MAX +#undef CHILD_MAX +#define CHILD_MAX (sysconf(_SC_CHILD_MAX)) +#endif + +#ifdef _SC_NGROUPS_MAX +#undef NGROUPS_MAX +#define NGROUPS_MAX (sysconf(_SC_NGROUPS_MAX)) +#endif + +#ifdef _SC_OPEN_MAX +#undef OPEN_MAX +#define OPEN_MAX (sysconf(_SC_OPEN_MAX)) +#endif + +#ifdef _SC_STREAM_MAX +#undef STREAM_MAX +#define STREAM_MAX (sysconf(_SC_STREAM_MAX)) +#endif + +#ifdef _SC_TZNAME_MAX +#undef TZNAME_MAX +#define TZNAME_MAX (sysconf(_SC_TZNAME_MAX)) +#endif + +#ifdef PID_T_MISSING +typedef int pid_t; +#endif + +#endif diff --git a/sdk/std/select.h b/sdk/std/select.h new file mode 100644 index 0000000..2812581 --- /dev/null +++ b/sdk/std/select.h @@ -0,0 +1,21 @@ +/* + * Find or use "replacement" select routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and use see license. + */ + +#ifndef __STD_SELECT_H__ +#define __STD_SELECT_H__ + +#ifdef SELECT_H_MISSING +#ifndef SYS_SELECT_H_MISSING +#include <sys/select.h> +#endif +#else +#include <select.h> +#endif + +#include <std/time.h> + +#endif diff --git a/sdk/std/signal.h b/sdk/std/signal.h new file mode 100644 index 0000000..b56b48a --- /dev/null +++ b/sdk/std/signal.h @@ -0,0 +1,11 @@ +#ifndef __STD_SIGNAL_H__ +#define __STD_SIGNAL_H__ + +#ifndef __CONFIG_H__ +#include <config.h> +#endif + +#include <signal.h> + +#endif + diff --git a/sdk/std/string.c b/sdk/std/string.c new file mode 100644 index 0000000..6f9649e --- /dev/null +++ b/sdk/std/string.c @@ -0,0 +1,110 @@ +/* + * Define constants used by other string services and case insensitive + * compare and conversion functions missing in some libc distributions. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <std/string.h> + +#ifdef STRLWR_F_MISSING + +char *strlwr(char *s) +{ + char *old; + + if(!s) + return NULL; + + old=s; + while(*s = (char)tolower(*s)) + ++s; + + return old; +} + +char *strupr(char *s) +{ + char *old; + + if(!s) + return NULL; + + old=s; + while(*s = (char)toupper(*s)) + ++s; + return old; +} + +#endif + +#ifdef STRDUP_F_MISSING + +char *strdup(str) +char *str; +{ + char *new = (char *)malloc(strlen(str) + 1); + if(!new) + return NULL; + + return strcpy(new, str); +} + +#endif + +#ifdef STRICMP_F_MISSING + +int stricmp(const char *s1, const char *s2) +{ + int t; + + while(*s1 && *s2) + { + if (t=tolower(*s1)-tolower(*s2)) + return t; + + ++s1; + ++s2; + } + return tolower(*s1)-tolower(*s2); +} + +int strnicmp(const char *s1,const char *s2, size_t n) +{ + int t; + + while (n--) + { + if (t=tolower(*s1)-tolower(*s2)) + return t; + + if (!*s1) + return 0; + + ++s1; + ++s2; + } + return 0; +} + +#endif + +#ifdef STRISTR_F_MISSING + +char *stristr(char *s1, const char *s2) +{ + int len = strlen(s2); + int count = strlen(s1) - len + 1; + + while(count--) + { + if(!strnicmp(s1, s2, len)) + return s1; + ++s1; + } + return NULL; +} + +#endif + diff --git a/sdk/std/string.h b/sdk/std/string.h new file mode 100644 index 0000000..bf642cf --- /dev/null +++ b/sdk/std/string.h @@ -0,0 +1,75 @@ +/* + * Portable string handling routines. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __STD_STRINGS_H__ +#define __STD_STRINGS_H__ + +#ifndef __STD_TYPES_H__ +#include <std/types.h> +#endif + +#include <string.h> +#include <ctype.h> + +#ifndef STRCASECMP_F_MISSING +#define stricmp(s1, s2) strcasecmp(s1, s2) +#define strnicmp(s1, s2, n) strncasecmp(s1, s2, n) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __NAMESPACE +#define __SPACES __NAMESPACE(__SPACES) +#endif + +extern char __SPACES[]; + +#ifdef STRICMP_F_MISSING +#ifdef __NAMESPACE +#define stricmp __NAMESPACE(stricmp) +#define strnicmp __NAMESPACE(strnicmp) +#endif + +int stricmp(const char *s1, const char *s2); +int strnicmp(const char *s1, const char *s2, size_t n); +#endif + +#ifdef STRLWR_F_MISSING + +#ifdef __NAMESPACE +#define strupr __NAMESPACE(strupr) +#define strlwr __NAMESPACE(strlwr) +#endif + +char *strlwr(char *s1); +char *strupr(char *s2); +#endif + +#ifdef STRDUP_F_MISSING + +#ifdef __NAMESPACE +#define strdup __NAMESPACE(strdup) +#endif + +char *strdup(const char *s); +#endif + +#ifdef STRISTR_F_MISSING +#ifdef __NAMESPACE +#define stristr __NAMESPACE(stristr) +#endif + +char *stristr(char *s1, const char *s2); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/std/sysexits.h b/sdk/std/sysexits.h new file mode 100644 index 0000000..208ec0e --- /dev/null +++ b/sdk/std/sysexits.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE 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. + * + * @(#)sysexits.h 4.8 (Berkeley) 4/3/91 + */ + +#ifndef _SYSEXITS_H +#define _SYSEXITS_H + +/* + * SYSEXITS.H -- Exit status codes for system programs. + * + * This include file attempts to categorize possible error + * exit statuses for system programs, notably delivermail + * and the Berkeley network. + * + * Error numbers begin at EX__BASE to reduce the possibility of + * clashing with other exit statuses that random programs may + * already return. The meaning of the codes is approximately + * as follows: + * + * EX_USAGE -- The command was used incorrectly, e.g., with + * the wrong number of arguments, a bad flag, a bad + * syntax in a parameter, or whatever. + * EX_DATAERR -- The input data was incorrect in some way. + * This should only be used for user's data & not + * system files. + * EX_NOINPUT -- An input file (not a system file) did not + * exist or was not readable. This could also include + * errors like "No message" to a mailer (if it cared + * to catch it). + * EX_NOUSER -- The user specified did not exist. This might + * be used for mail addresses or remote logins. + * EX_NOHOST -- The host specified did not exist. This is used + * in mail addresses or network requests. + * EX_UNAVAILABLE -- A service is unavailable. This can occur + * if a support program or file does not exist. This + * can also be used as a catchall message when something + * you wanted to do doesn't work, but you don't know + * why. + * EX_SOFTWARE -- An internal software error has been detected. + * This should be limited to non-operating system related + * errors as possible. + * EX_OSERR -- An operating system error has been detected. + * This is intended to be used for such things as "cannot + * fork", "cannot create pipe", or the like. It includes + * things like getuid returning a user that does not + * exist in the passwd file. + * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, + * etc.) does not exist, cannot be opened, or has some + * sort of error (e.g., syntax error). + * EX_CANTCREAT -- A (user specified) output file cannot be + * created. + * EX_IOERR -- An error occurred while doing I/O on some file. + * EX_TEMPFAIL -- temporary failure, indicating something that + * is not really an error. In sendmail, this means + * that a mailer (e.g.) could not create a connection, + * and the request should be reattempted later. + * EX_PROTOCOL -- the remote system returned something that + * was "not possible" during a protocol exchange. + * EX_NOPERM -- You did not have sufficient permission to + * perform the operation. This is not intended for + * file system problems, which should use NOINPUT or + * CANTCREAT, but rather for higher level permissions. + */ + +#define EX_OK 0 /* successful termination */ + +#define EX__BASE 64 /* base value for error messages */ + +#define EX_USAGE 64 /* command line usage error */ +#define EX_DATAERR 65 /* data format error */ +#define EX_NOINPUT 66 /* cannot open input */ +#define EX_NOUSER 67 /* addressee unknown */ +#define EX_NOHOST 68 /* host name unknown */ +#define EX_UNAVAILABLE 69 /* service unavailable */ +#define EX_SOFTWARE 70 /* internal software error */ +#define EX_OSERR 71 /* system error (e.g., can't fork) */ +#define EX_OSFILE 72 /* critical OS file missing */ +#define EX_CANTCREAT 73 /* can't create (user) output file */ +#define EX_IOERR 74 /* input/output error */ +#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ +#define EX_PROTOCOL 76 /* remote error in protocol */ +#define EX_NOPERM 77 /* permission denied */ +#define EX_CONFIG 78 /* configuration error */ + +#define EX__MAX 78 /* maximum listed value */ + +#endif /* !_SYSEXITS_H */ diff --git a/sdk/std/time.h b/sdk/std/time.h new file mode 100644 index 0000000..45c42cb --- /dev/null +++ b/sdk/std/time.h @@ -0,0 +1,23 @@ +/* + * Portable header access into time functions. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __STD_TIME_H__ +#define __STD_TIME_H__ + +#ifndef __CONFIG_H__ +#include <config.h> +#endif + +#include <time.h> + +#ifndef SYS_TIME_H_MISSING +#include <sys/time.h> +#endif + +#endif + + diff --git a/sdk/std/types.h b/sdk/std/types.h new file mode 100644 index 0000000..ebd4ea7 --- /dev/null +++ b/sdk/std/types.h @@ -0,0 +1,54 @@ +/* + * Portable common datatype declarations. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#ifndef __STD_TYPES_H__ +#define __STD_TYPES_H__ + +#ifndef __CONFIG_H__ +#include <config.h> +#endif + +#include <sys/types.h> +#include <stdlib.h> + +#ifdef UCHAR_T_MISSING +typedef unsigned char uchar; +#endif + +#ifdef USHORT_T_MISSING +typedef unsigned short ushort; +#endif + +#ifdef ULONG_T_MISSING +typedef unsigned long ulong; +#endif + +#ifdef __cplusplus +enum +{ + FALSE=0, + TRUE +}; +#else +typedef enum +{ + FALSE=0, + TRUE +} bool; +#endif + +typedef void *ptr_t; + +#ifdef SIZE_T_MISSING +typedef unsigned int size_t; +#endif + +#ifdef SSIZE_T_MISSING +typedef int ssize_t; +#endif + +#endif diff --git a/sdk/std/utmp.c b/sdk/std/utmp.c new file mode 100644 index 0000000..78cbf64 --- /dev/null +++ b/sdk/std/utmp.c @@ -0,0 +1,49 @@ +/* + * Portable emulation of utmp access routines, such as for broken BSD. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and use see license. + */ + +#include <std/utmp.h> +#include <std/files.h> + +#ifdef GETUTENT_F_MISSING + +static fd_t ut = -1; +static struct utmp utmp; + +void setutent(void) +{ + if(ut < 0) + ut = open(_PATH_UTMP, O_RDONLY); + if(ut < 0) + return; + + lseek(ut, 0l, SEEK_SET); +} + +void endutent(void) +{ + if(ut > -1) + { + close(ut); + ut = -1; + } +} + +struct utmp *getutent(void) +{ + if(ut < 0) + setutent(); + + if(ut < 0) + return NULL; + + if(read(ut, &utmp, sizeof(utmp)) < sizeof(utmp)) + return NULL; + + return &utmp; +} + +#endif diff --git a/sdk/std/utmp.h b/sdk/std/utmp.h new file mode 100644 index 0000000..2ac67f4 --- /dev/null +++ b/sdk/std/utmp.h @@ -0,0 +1,31 @@ +/* + * utmp file access interface, local or ported. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and use see license. + */ + +#ifndef __STD_UTMP_H__ +#define __STD_UTMP_H__ + +#ifndef __STD_TYPES_H__ +#include <std/types.h> +#endif + +#include <utmp.h> + +#ifndef _UTMP_PATH +#define _UTMP_PATH "/etc/utmp.h" +#endif + +#ifdef UT_USER_I_MISSING +#define ut_user ut_name +#endif + +#ifdef GETUTENT_F_MISSING +void setutent(void); +void endutent(void); +struct utmp *getutent(void); +#endif + +#endif diff --git a/speak.lsm b/speak.lsm new file mode 100644 index 0000000..d96b4d5 --- /dev/null +++ b/speak.lsm @@ -0,0 +1,23 @@ +Begin3 +Title: SPO256-AL2 Text-to-Speech Services +Version: 1.0 +Entered-date: March 23, 1997 +Description: This package comprises a network TCP text-to-speech server + designed for the SPO256-AL2 text-to-speech board, as + described in the January '97 issue of the Linux Journal. + This server is now implemented as a generic rc.d startable + "service" with standardized (server independent) utilities, + and may be used to develop other network-wide text-to-speech + services for different hardware. This release adds new + functionality to both the server and vmon utilities. +Keywords: talk, cti, tsw, tycho, lj, spo256, vocoder +Author: dyfet@tycho.com (David Sugar) +Maintained-by: dyfet@tycho.com (David Sugar) +Primary-site: ftp.tycho.com /dist + 58 kb speak-0.3.tar.gz + 1 kb speak.lsm +Alternate-site: sunsite.unc.edu: no idea where +Original-site: http://www.tycho.com/packages/speak +Platform: Should be portable to virtually any UNIX system. +Copying-policy: Free, public, terms similar to BSD on redistribution. +End diff --git a/spktrapd/README.NOW b/spktrapd/README.NOW new file mode 100644 index 0000000..957e196 --- /dev/null +++ b/spktrapd/README.NOW @@ -0,0 +1,8 @@ +Future package! + +The spktrapd module will be a snmptrapd that redirects snmp traps verbally to +the speak service using device and enterprise specific rules and tables. +This will allow verbal monitering and alerts for a variety of network +devices. + + diff --git a/spo256/Makefile.in b/spo256/Makefile.in new file mode 100644 index 0000000..6e21ea4 --- /dev/null +++ b/spo256/Makefile.in @@ -0,0 +1,34 @@ +# +# Template to build spo256-AL2 text-to-speech server. +# $Id: Makefile.in 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ +# Copyright (c) 1997 by Tycho Softworks. +# + +OBJS = speak.o spo.o getspo.o words.o chars.o getidx.o client.o \ + number.o currency.o +PROGS = spo256 +START = 10 +RUNLVLS = 3 + +all: $(PROGS) + +install: $(PROGS) + install -s -g bin $(PROGS) $(SBINDIR) + ln -sf $(SBINDIR)/spo256 $(BINDIR)/speak + install -g bin speak.conf $(SYSCONFDIR) + ../sdk/bin/instinit speak $(START) $(RUNLVLS) + ../sdk/bin/instsvc services speak 800/tcp \# SPO256-AL2 Text-to-Speech service + ../sdk/bin/instman $(MANDIR) 1 speak + ../sdk/bin/instman $(MANDIR) 7 speak.conf + ../sdk/bin/instman $(MANDIR) 8 spo256 + +clean: + -rm $(PROGS) + -rm $(OBJS) + +.c.o: + $(CC) $(CFLAGS) $(OPTIMIZE) -I../sdk -o $@ -c $< + +spo256: $(OBJS) + $(CC) $(CFLAGS) -L../sdk/lib $(LIBS) -o $@ $(OBJS) $(LIBS) + diff --git a/spo256/README b/spo256/README new file mode 100644 index 0000000..29c2fae --- /dev/null +++ b/spo256/README @@ -0,0 +1,24 @@ +This particular SPO256 server is able to translate common usages for numbers +and perform word substitution. For example, the number 123.45 is pronounced +as "one hundred twenty three point four five". Internet names and addresses +are also pronounced correctly to a large extent. The support of different +usages and idioms in this server is not yet as complete as the WorldVU SPO +server, but this is being worked on. + +The SPO server was rewritten in release 0.3 with a character state parser +to allow better parsing for and pacing of spoken text. The 0.3 state +parser now recognizes embedded server command sequences as well as text +that is to be spoken. Embedded server commands are proceeded by the +<ESC> character, and appear in <>'s, using a format much like mark-up tags. +For example, word "spelling" can be turned on or off with <ESC><spell> and +<ESC></spell>. The current tags supported by the SPO256 server are found +in the spo256 man page. More tags will be added as they appear feasable to +create. + +This SPO server differs from the original WorldVU server in that it can +also be used in a client role to pipe standard output to the server. One +can enter "cat filename | spo256 localhost" (or "cat filename | speak +localhost") to redirect output to the spo server running on the local +machine, for example. + + diff --git a/spo256/chars.c b/spo256/chars.c new file mode 100644 index 0000000..e4b2a2a --- /dev/null +++ b/spo256/chars.c @@ -0,0 +1,339 @@ +/* + * Character state parser for text-to-speech server. + * $Id: chars.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> +#include <other/config.h> +#include <std/files.h> +#include <std/process.h> +#include "speak.h" + +enum +{ + CH_IGNORE, + CH_PERIOD, + CH_QUOTE, + CH_ESCAPE, + CH_SPACE, + CH_ALPHA, + CH_NUMERIC, + CH_PUNCT, +}; + +static uchar map[256]; +static uchar word[256]; +static int cpos = 0; +static bool init = FALSE; +static void (*state)(uchar ch); +static bool quote; + +static void s_hex(uchar ch); +static void s_num(uchar ch); +static void s_cmd(uchar ch); +static void s_leadcmd(uchar ch); +static void s_abbrev(uchar ch); +static void s_point(uchar ch); +static void s_word(uchar ch); +static void s_idle(uchar ch); + +static void s_hex(uchar ch) +{ + switch(ch) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'a': + case 'A': + case 'b': + case 'B': + case 'c': + case 'C': + case 'd': + case 'D': + case 'e': + case 'E': + case 'f': + case 'F': + word[cpos++] = ch; + break; + default: + word[cpos] = 0; + number(word); + state = s_idle; + s_idle(ch); + } +} + +static void s_num(uchar ch) +{ + switch(map[ch]) + { + case CH_NUMERIC: + word[cpos++] = ch; + break; + default: + switch(ch) + { + case 'e': + case '^': + word[cpos++] = ch; + number(word); + cpos = 0; + spo_word("raised"); + spo_word("to"); + spo_word("the"); + spo_word("power"); + break; + case ':': + case '/': + case '.': + word[cpos++] = ch; + break; + case '%': + word[cpos] = 0; + number(word); + state = s_idle; + spo_word("percent"); + break; + case 'x': + case 'X': + if(cpos == 1) + { + cpos = 0; + state = s_hex; + break; + } + default: + word[cpos] = 0; + number(word); + state = s_idle; + s_idle(ch); + } + } +} + +static void s_cmd(uchar ch) +{ + if(ch == '>') + { + word[cpos] = 0; + spo_cmd((char *)word); + state = s_idle; + } + else + word[cpos++] = ch; +} + +static void s_leadcmd(uchar ch) +{ + if(ch == '<') + state = s_cmd; + else + { + state = s_idle; + s_idle(ch); + } +} + +static void s_abbrev(uchar ch) +{ + switch(map[ch]) + { + case CH_SPACE: + abbrev((char *)word); + state = s_idle; + break; + default: + spo_word((char *)word); + cpos = 0; + spo_word("dot"); + state = s_word; + s_word(ch); + } +} + +static void s_point(uchar ch) +{ + switch(map[ch]) + { + case CH_ALPHA: + state = s_word; + case CH_PERIOD: + spo_word("dot"); + break; + case CH_NUMERIC: + spo_word("point"); + state = s_num; + break; + default: + state = s_idle; + break; + } +} + +static void s_word(uchar ch) +{ + switch(map[ch]) + { + case CH_PERIOD: + if(!cpos) + state = s_point; + else + state = s_abbrev; + word[cpos++] = '.'; + word[cpos] = 0; + break; + case CH_PUNCT: + case CH_ALPHA: + case CH_NUMERIC: + if(cpos < 255) + word[cpos++] = ch; + break; + case CH_SPACE: + word[cpos] = 0; + spo_word((char *)word); + state = s_idle; + break; + default: + switch(ch) + { + case '\'': + word[cpos++] = ch; + break; + default: + word[cpos] = 0; + spo_word((char *)word); + spo_pause(P_WORD); + state = s_idle; + s_idle(ch); + } + } +} + +static void s_idle(uchar ch) +{ + cpos = 0; + switch(map[ch]) + { + case CH_NUMERIC: + state = s_num; + s_num(ch); + break; + case CH_ALPHA: + state = s_word; + s_word(ch); + break; + case CH_ESCAPE: + state = s_leadcmd; + break; + case CH_SPACE: + spo_pause(P_WORD); + break; + case CH_QUOTE: + if(quote) + { + spo_word("end"); + quote = FALSE; + } + else + quote = TRUE; + spo_word("quote"); + break; + default: + switch(ch) + { + case '$': + word[0] = '$'; + cpos = 1; + state = s_num; + break; + case '*': + spo_word("times"); + break; + case '/': + spo_word("divided"); + spo_word("by"); + break; + case '+': + spo_word("plus"); + break; + case '-': + spo_word("minus"); + break; + case '&': + spo_word("and"); + break; + case '|': + spo_word("or"); + break; + case '~': + spo_word("not"); + break; + case ')': + spo_word("end"); + case '(': + spo_word("parenthesis"); + break; + case '=': + spo_word("equals"); + break; + case '<': + spo_word("less"); + spo_word("than"); + break; + case '>': + spo_word("greater"); + spo_word("than"); + break; + default: + spo_pause(P_WORD); + } + } +} + +void chars(FILE *fp) +{ + int i, ch; + + quote = FALSE; + state = s_idle; + + if(!init) + { + for(i = 0; i < 256; ++i) + map[i] = CH_IGNORE; + + map[27] = CH_ESCAPE; + + for(i = 33; i < 127; ++i) + map[i] = CH_PUNCT; + + map[9] = map[13] = map[10] = map[32] = CH_SPACE; + for(i = 48; i < 58; ++i) + map[i] = CH_NUMERIC; + + for(i = 0; i < 26; ++i) + { + map[i + 65] = CH_ALPHA; + map[i + 97] = CH_ALPHA; + } + map['.'] = CH_PERIOD; + map['\"'] = CH_QUOTE; + } + + while(EOF != (ch = fgetc(fp))) + (*state)(ch); + + (*state)(0); +} diff --git a/spo256/client.c b/spo256/client.c new file mode 100644 index 0000000..b43696f --- /dev/null +++ b/spo256/client.c @@ -0,0 +1,40 @@ +/* + * Client operating mode. + * $Id: client.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + * + * Abstract: + * The client mode of operation will connect to SPO256 server and + * redirect standard output to the server. This allows the speak + * (spo256) image to be used to terminate pipes. + */ + +#include <std/process.h> +#include <other/string.h> +#include <std/files.h> +#include <other/config.h> +#include <net/socket.h> +#include <net/stream.h> +#include "speak.h" + +void client(char *hostname, ushort port) +{ + STREAM fp = opentcp(hostname, port); + char buf[1024]; + + if(!fp) + fatal(EX_UNAVAILABLE, "spo256: %s: unkown host\n", hostname); + + gettcp(buf, sizeof(buf) - 1, fp); /* get banner line */ + while(!feof(stdin)) + { + fgets(buf, sizeof(buf) - 1, stdin); + if(feof(stdin)) + break; + + puttcp(buf, fp); + } + closetcp(fp); + exit(0); +} diff --git a/spo256/currency.c b/spo256/currency.c new file mode 100644 index 0000000..b79c036 --- /dev/null +++ b/spo256/currency.c @@ -0,0 +1,43 @@ +/* + * Currency rules, for USD. + * $Id: currency.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> +#include <other/config.h> +#include "speak.h" + +void currency(char *str) +{ + char *cents; + ++str; + + cents = strchr(str, '.'); + if(cents) + *(cents++) = 0; + + if(atol(str) != 0) + { + number(str); + if(atol(str) > 1) + spo_word("dollars"); + else + spo_word("dollar"); + } + + if(cents) + { + if(atol(str) > 0) + spo_word("and"); + + number(cents); + if(atoi(cents) > 1) + spo_word("cent"); + else + spo_word("cents"); + } +} + + diff --git a/spo256/getidx.c b/spo256/getidx.c new file mode 100644 index 0000000..70a730c --- /dev/null +++ b/spo256/getidx.c @@ -0,0 +1,98 @@ +/* + * Build word and abbreviation index in memory from .conf. + * $Id: getidx.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> +#include <other/config.h> +#include <std/files.h> +#include <std/process.h> +#include <other/memory.h> +#include "speak.h" + +MEMPOOL *mem; +IDX **widx, **aidx; + +static int key(uchar *str) +{ + unsigned int k = 0; + int len = strlen((char *)str); + + while(*str) + { + k = (k * 7) | (*str & 0x1f); + ++str; + } + + k |= len; + + return (k % KEYSIZE); +} + +void getidx(CONFIG *cfg) +{ + int i; + char *p, *q; + IDX *new; + + mem = mempool(16384, 16); + + widx = (IDX **)memreq(mem, sizeof(IDX *) * KEYSIZE); + aidx = (IDX **)memreq(mem, sizeof(IDX *) * KEYSIZE); + + + for(i = 0; i < KEYSIZE; ++i) + widx[i] = aidx[i] = NULL; + + seek_config(cfg, "words"); + while(NULL != (p = read_config(cfg))) + { + q = strchr(p, '='); + if(!q) + continue; + + *(q++) = 0; + p = strtrim(p, __SPACES); + q = strtrim(q, __SPACES); + i = key((uchar *)p); + new = memlreq(mem, sizeof(IDX)); + new->word_link = widx[i]; + widx[i] = new; + new->word_key = strreq(mem, p); + new->word_spo = strreq(mem, q); + } + seek_config(cfg, "abbrev"); + while(NULL != (p = read_config(cfg))) + { + q = strchr(p, '='); + if(!q) + continue; + + *(q++) = 0; + p = strtrim(p, __SPACES); + q = strtrim(q, __SPACES); + i = key((uchar *)p); + new = memlreq(mem, sizeof(IDX)); + new->word_link = aidx[i]; + aidx[i] = new; + new->word_key = strreq(mem, p); + new->word_spo = strreq(mem, q); + } +} + +char *find(IDX **table, char *str) +{ + IDX *next = table[key((uchar *)str)]; + + + while(next) + { + if(!stricmp(str, next->word_key)) + return next->word_spo; + + next = next->word_link; + } + return NULL; +} diff --git a/spo256/getspo.c b/spo256/getspo.c new file mode 100644 index 0000000..5ff64d7 --- /dev/null +++ b/spo256/getspo.c @@ -0,0 +1,68 @@ +/* + * Parse .conf file interface spec for spo communications. + * $Id: getspo.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> +#include <other/config.h> +#include <std/files.h> +#include <proc/process.h> +#include <dev/tty.h> + +char *mask = NULL; + +int getspo(CONFIG *cfg) +{ + int spo = -1; + char *p; + stty_t stty; + + if(!seek_config(cfg, "interface")) + fatal(EX_CONFIG, "spo256: [interface]: missing from speak.conf\n"); + + while(NULL != read_config(cfg)) + { + if(NULL != (p = get_config(cfg, "bind"))) + { + mask = strdup(p); + continue; + } + + if(NULL != (p = get_config(cfg, "device"))) + { + spo = open(p, O_RDWR); + if(spo < 0) + fatal(EX_UNAVAILABLE, "spo256: %s: cannot access\n", p); + stty = getstty(spo); + interactive(stty, FALSE); + setflowctrl(stty, FC_HARD); + continue; + } + + if(NULL != (p = get_config(cfg, "speed"))) + { + if(spo < 0) + fatal(EX_CONFIG, "spo256: set speed for unspecified device\n"); + setspeed(stty, atol(p)); + continue; + } + + if(NULL != (p = get_config(cfg, "parity"))) + { + if(spo < 0) + fatal(EX_CONFIG, "spo256: set format for unspecified device\n"); + if(!stricmp(p, "even")) + setformat(stty, "7e1"); + if(!stricmp(p, "odd")) + setformat(stty, "7o1"); + if(!stricmp(p, "none")) + setformat(stty, "8n1"); + continue; + } + } + putstty(spo, stty, TRUE); + return spo; +} + diff --git a/spo256/number.c b/spo256/number.c new file mode 100644 index 0000000..16c662a --- /dev/null +++ b/spo256/number.c @@ -0,0 +1,132 @@ +/* + * Number base pronounciation rules and special cases. + * $Id: number.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + */ + +#include <other/string.h> +#include <other/config.h> +#include "speak.h" + +static char *nteen[] = { + "ten", "eleven", "twelve", "thirteen", "fourteen", + "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"}; + +static char *n10[] = { + "zero", "ten", "twenty", "thirty", "fourty", + "fifty", "sixty", "seventy", "eighty", "ninety"}; + + +static void digits(long value) +{ + bool hundred = FALSE; + char buf[2]; + + if(value >= 100) + { + digits(value / 100); + spo_word("hundred"); + value %= 100; + hundred = TRUE; + } + + if(!value && hundred) + return; + + if(value >= 20) + { + spo_word(n10[value / 10]); + value %= 10; + if(!value) + return; + } + + if(value < 10) + { + buf[0] = value + '0'; + buf[1] = 0; + spo_word(buf); + return; + } + spo_word(nteen[value - 10]); +} + +void number(char *str) +{ + char *p; + long value = atol(str); + + if(lit || spell) + { + spo_word(str); + return; + } + + /* Check for w.x.y.z as "w dot x dot y dot z" */ + + if(ccount(str, ".") > 1) + { + while(NULL != (p = strchr(str, '.'))) + { + *(p++) = 0; + number(str); + str = p; + } + number(str); + return; + } + + if(NULL != (p = strchr(str, '.'))) + { + *(p++) = 0; + number(str); + spo_word("point"); + spo_word(p); + return; + } + + if(NULL != (p = strchr(str, ':'))) + { + digits(atol(str)); + ++p; + if(atol(p) < 10) + if(atol(p)) + write(spo, " O ", 2); + + if(atol(p)) + digits(atol(p)); + + if(NULL != (p = strchr(p, ':'))) + { + spo_word("and"); + digits(atol(++p)); + spo_word("seconds"); + } + else + { + p = str; + if(strchr(p, 'a') || strchr(p, 'A')) + write(spo, "A M ", 5); + if(strchr(p, 'p') || strchr(p, 'P')) + write(spo, "P M ", 5); + } + return; + } + + if(value >= 1000000l) + { + digits(value / 1000000l); + spo_word("million"); + value %= 1000000l; + } + + if(value >= 1000) + { + digits(value / 1000); + spo_word("thousand"); + value %= 1000; + } + + digits(value); +} diff --git a/spo256/speak.1 b/spo256/speak.1 new file mode 100644 index 0000000..8ceac59 --- /dev/null +++ b/spo256/speak.1 @@ -0,0 +1,46 @@ +.TH "speak" "1" "January 1997" "Speak 0.2" "Text-to-Speech" +.PP +.SH NAME +.PP +\fBspeak\fP - send output to text-to-speech service. +.PP +.SH SYNOPSIS +.PP +\fBspeak\fP [\fIhostname\fP] +.PP +.SH DESCRIPTION +.PP +The Text-to-speech package introduces a standard TCP/IP port service for +attaching text-to-speech resources to your network. These resources can +be used to monitor system status, provide verbal alarms, etc. This network +service may be accessed by telnetting to a machine running a "speak" server, +or by using the various application utilities, such as \fBspeak\fP. +.PP + +The \fBspeak\fP program will capture and redirect all standard input to the +network speech server, such as \fBspo256\fP, running either on the +local machine ("\fIlocalhost\fP"), or to the server running on the host +specified as a command line argument. \fBspeak\fP is normally used to +terminate a pipe, such as in "\fIcat filename | speak\fP". The TCP service +port used for the connection is specified in \fI/etc/services\fP. + +.PP +While most of the text-to-speech programs are separately written, the +\fBspeak\fP program is normally an alias for the actual server itself, +such as the \fBspo256\fP program. This was intentional, as future +versions of speak may drive hardware directly in an alternate usage +(such as "\fIspeak /dev/ttyxx\fP"), as well as redirecting output to a named +host. + +.PP +.SH SEE ALSO +.PP +.BR say (1), +.BR down (8), +.BR spo256 (8), +.BR services (7) +.PP +.SH AUTHOR +.PP +David Sugar (dyfet@tycho.com) +.PP diff --git a/spo256/speak.8 b/spo256/speak.8 new file mode 100644 index 0000000..aaeceef --- /dev/null +++ b/spo256/speak.8 @@ -0,0 +1,39 @@ +.TH "spo256" "8" "1997" "Text-to-Speech services" "Tycho Softworks" +.PP +.SH "NAME spo256 \- SPO256-AL2 Text-to-Speech Server" +.PP +.SH "SYNOPSIS" +.PP +\fBspo256\fP +.br +\fBspeak\fP [hostname] +.PP +.SH "DESCRIPTION" +.PP +.SH "FILES" +.PP +The spo256 server configuration may be found in \fB/etc/speak.conf\fP. +.PP +.SH "SEE ALSO" +.PP +.IP +.IP o +\fBdown(8)\fP: Shuts down the system. +.IP +.IP o +\fBsay(1)\fP: Sends output to a "speak" server. +.IP +.IP o +\fBservices(5)\fP: Installed TCP/IP network services. +.IP +.PP +.SH "DIAGNOSTICS" +.PP +\fBspo256\fP will warn and fail to load if the "speak" services entry +is missing, if the device cannot be opened, or if the speak.conf file +is missing. +.PP +.SH "AUTHOR" +.PP +David Sugar (dyfet@tycho.com) +.PP diff --git a/spo256/speak.c b/spo256/speak.c new file mode 100644 index 0000000..7de099f --- /dev/null +++ b/spo256/speak.c @@ -0,0 +1,86 @@ +/* + * Base (main) for spo server. + * $Id: speak.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + * + * Abstract: + * Establish basic operating environment for SPO256-AL2 text-to-speech + * server. This module verifies system configuration, parses the + * config files for word lists that are stored in the quick-lookup + * internal hash word subsitution database, binds the server to a tcp + * network port, and accepts client requests. + */ + +#include <proc/process.h> +#include <std/string.h> +#include <std/files.h> +#include <other/config.h> +#include <net/socket.h> +#include <net/stream.h> +#include "speak.h" + +int spo; /* device id of spo */ +FILE *io; + +void main(int argc, char **argv) +{ + int port = getservice("speak"); + CONFIG *cfg; + SOCKET so; + char buf[1024]; + + if(!port) + fatal(EX_UNAVAILABLE, "spo256: speak: service not defined in /etc/services\n"); + + if(argc < 1 || argc > 2) + fatal(EX_USAGE, "use: spo256 [hostname]\n"); + + if(argc > 1) + client(argv[1], port); + + if(!stricmp(pathfname(argv[0]), "speak")) + client("localhost", port); + + if(NULL == (cfg = sys_config("speak"))) + fatal(EX_CONFIG, "spo256: speak.conf: config file missing\n"); + + /* get device configuration */ + + spo = getspo(cfg); + + getidx(cfg); + close_config(cfg); + + /* bind server to socket */ + + so = tcpsocket(mask, port, 5); + if(so == INVALID_SOCKET) + fatal(EX_UNAVAILABLE, "spo256: %d: failed to bind port\n", port); + + /* now, make ourselves a daemon */ + + pdetach(D_KEEPNONIO); + + /* Main loop of server. The server accepts one connection in + turn from each requesting user application. The remaining + application requests are kept in backlog while the current + application is served. This assures non-overlapping speech. + */ + + for(;;) + { + io = accepttcp(so); + if(!io) + continue; + + spo_init(); + puttcp("SPO256-AL2 Text-to-Speech Server 1.0\r\n", io); + + chars(io); + + spo_pause(P_END); + closetcp(io); + } +} + diff --git a/spo256/speak.conf.7 b/spo256/speak.conf.7 new file mode 100644 index 0000000..ccc3e57 --- /dev/null +++ b/spo256/speak.conf.7 @@ -0,0 +1,72 @@ +.TH "speak.conf" "7" "January 1997" "Speak 0.2" "Text-to-Speech" +.PP +.SH NAME +.PP +\fBspeak.conf\fP - configuration file for text-to-speech services. +.PP +.SH SYNOPSIS +.PP +\fBspeak.conf\fP +.PP +.SH DESCRIPTION +.PP +The \fBspeak.conf\fP file is a text edit-able configuration file used by the +text-to-speech server and various text-to-speech utilities. +.PP +\fBspeak.conf\fP is divided into sections, donated with "[]"'s. These +sections include hardware parameters for the text-to-speech server used on the +local machine, translation tables used for phonetic dictionaries by text-to- +speech servers, and runtime default information for specific programs. On +machines that do not run their own text-to-speech server, \fBspeak.conf\fP +will still be used to specify runtime defaults for utility programs that are +present. +.PP +.SH FILE FORMAT +.PP +The file consists of sections and parameters. A section begins with the +name of the section in square brackets and continues until the next section +begins. Sections contain parameters of the form \'name = value`'. +.PP +The file is line-based text - that is, each newline-terminated line +represents either a comment, a section name, or a parameter. Parameters +in the .conf file normally do not appear on multiple lines, except for +several specific exceptions (lists and tables) that are not used in this +package. +.PP +Section and parameter names are not case sensitive. +.PP +Only the first equal sign in a parameter is significant. Whitepsaces before +or after the = are ignored. Leading and trailing whitespaces are ignored. +Whitepaces within a parameter name are also ignored, while whitespaces +within a parameter value are preserved. +.PP +Any line beginning with a semicolon or a pound sign is treated as a comment +and is ignored. +.PP +Any line containing a list, in the form 'name = { v1 v2 v3 }' may be +continued over multiple lines if the terminating '}' is not found in the +current line. +.PP +Any line beginning with a plus is considered a repeat of the "name =" portion +of the last parameter line. This is often used to build up hostname lists +when multiple hostnames may be specified. +.PP +The parameter value may either be quoted or unquoted. Quoted parameters +values may be used to specify lead or trailing spaces which would otherwise +be ignored. Either matching single or double quotes may be used, and the +quotes are not kept as part of the value returned to the application. +.PP +Parameter values may either be strings, numeric values, or boolean flags. +When a boolean parameter is used, the characters "T" for 'true' and "F" for +'false' may be used. The full word, "true" and "false", may also be +spelled out. "Y" or "Yes" and "N" or "No" may also be used for "true" or +"false". +.PP +.SH SEE ALSO +.PP +.BR speak (1) +.PP +.SH AUTHOR +.PP +David Sugar (dyfet@tycho.com) +.PP diff --git a/spo256/speak.h b/spo256/speak.h new file mode 100644 index 0000000..07b9875 --- /dev/null +++ b/spo256/speak.h @@ -0,0 +1,48 @@ +/* + * Master header for spo server. + * $Id$ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and use see license. + * + * Abstract: + * Define internal hash index system to quickly find text for + * substitutions. The spo-256 is driven by substitution tables + * which provide alternate spellings to adjust mis-pronounced + * speech. + */ + +typedef enum +{ + P_END, /* Finish line off, send SPO-end mark */ + P_LINE, /* Send nl because we have a empty line */ + P_SENTANCE, /* Pause at end of sentance (nl) */ + P_WORD /* Inter-word delay (spaces) */ +} PAUSE; + +#define KEYSIZE 791 /* Size of internal hash database keyrange */ + +typedef struct _idx +{ + struct _idx *word_link; /* hash link chain */ + char *word_key; /* initial word & hash key */ + char *word_spo; /* substitute spelling */ +} IDX; + +extern int spo; +extern IDX **widx, **aidx; +extern char *mask; +extern FILE *io; +extern bool echo, spell, lit; + +void abbrev(char *str); +int getspo(CONFIG *cfg); +void getidx(CONFIG *cfg); +char *find(IDX **table, char *str); +void client(char *hostname, ushort port); + +void spo_init(void); +void spo_cmd(char *str); +void spo_word(char *str); +void spo_pause(PAUSE); +void spo_begquote(void); +void spo_endquote(void); diff --git a/spo256/speak.init b/spo256/speak.init new file mode 100644 index 0000000..0c46b8a --- /dev/null +++ b/spo256/speak.init @@ -0,0 +1,54 @@ +#!/bin/sh + +# modify FILESYSTEMS to activate and use vmon. +FILESYSTEMS="/" + +mode=$1 + +if [ $# = 0 ] ; then + mode='rc' +fi + +if [ ! "$mode" = 'rc' ] ; then + # Source function library. + . /etc/rc.d/init.d/functions + + # Source networking configuration. + . /etc/sysconfig/network + + # Check that networking is up. + [ ${NETWORKING} = "no" ] && exit 0 +fi + +# See how we were called. +case "$mode" in + rc) + echo "Starting SPO256-AL2 server" + spo256 + if [ ! -z "$FILESYSTEMS" ] ; then + vmon $FILESYSTEMS + fi + ;; + start) + echo -n "Starting SPO256-AL2 speech services: " + daemon spo256 + if [ ! -z "$FILESYSTEMS" ] ; then + daemon vmon $FILESYSTEMS + fi + echo + touch /var/lock/subsys/speak + ;; + stop) + echo -n "Shutting down SPO256-AL2 speech services: " + killproc spo256 + if [ ! -z "$FILESYSTEMS" ] ; then + killproc vmon + fi + rm -f /var/lock/subsys/speak + echo "" + ;; + *) + echo "Usage: speak.init {start|stop}" + exit 1 +esac + diff --git a/spo256/spo.c b/spo256/spo.c new file mode 100644 index 0000000..5c4f7ec --- /dev/null +++ b/spo256/spo.c @@ -0,0 +1,161 @@ +/* + * SPO256 low level operations. + * $Id: spo.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions on distribution and reuse see product license. + * + * Abstract: + * Key SPO translation modules. This includes the word substution + * module, the numeric pronounciation system, pause control, and + * other low level spo services. + */ + +#include <other/config.h> +#include <other/string.h> +#include "speak.h" + +/* + * Flags and operating mode properties that may now be effected by + * server commands. + */ + +bool echo = FALSE; /* echo SPO output to user? */ +bool spell = FALSE; /* spell all words? */ +bool lit = FALSE; /* literally pronounce as is? */ + +/* + * A new 'init' function is added to initialize operating state for + * each new connection. This assures that spo command sequences + * issued from a previous session are not left in effect. + */ + +void spo_init(void) +{ + echo = FALSE; /* echo off by default */ + spell = FALSE; + lit = FALSE; +}; + +/* + * Interpret server specific commands embedded in <ESC><cmd> + * sequences. The SPO has limited options to effect in this manner. + */ + +void spo_cmd(char *str) +{ + if(!stricmp(str, "echo")) + { + echo = TRUE; + return; + } + + if(!stricmp(str, "/echo")) + { + echo = FALSE; + return; + } + + if(!stricmp(str, "spell")) + { + spell = TRUE; + return; + } + + if(!stricmp(str, "/spell")) + { + spell = FALSE; + return; + } + + if(!stricmp(str, "lit")) + { + lit = TRUE; + return; + } + + if(!stricmp(str, "/lit")) + { + lit = FALSE; + return; + } +}; + +/* + * Pause spo output between words, numbers, and empty lines, so that + * words are properly announciated. This is typically accomplished with + * spaces and newline control. + */ + +void spo_pause(PAUSE p) +{ + switch(p) + { + case P_WORD: + write(spo, " ", 1); + if(echo) + puttcp(" ", io); + break; + case P_SENTANCE: + write(spo, " \n", 2); + if(echo) + puttcp(" \n", io); + break; + case P_LINE: + write(spo, " \r\n", 3); + if(echo) + puttcp(" \r\n", io); + break; + case P_END: + write(spo, "\r\n", 2); + } +} + +/* Announce quoted text. */ + +void spo_begquote(void) +{ + spo_word("quote"); +} + +void spo_endquote(void) +{ + spo_word("end"); + spo_begquote(); +} + +/* + * This performs low level lookup and pronounciation of words, either + * in the originally submitted spelling, or in the spo dictionary + * spelling. + */ + +void spo_word(char *word) +{ + char *p = find(widx, word); + if(!p) + p = word; + + if(lit) + p = word; + + if(spell) + { + p = word; + while(*p) + { + write(spo, p, 1); + if(echo) + fputc(*p, io); + spo_pause(P_WORD); + ++p; + } + } + else + { + write(spo, p, strlen(p)); + if(echo) + puttcp(p, io); + } + spo_pause(P_WORD); +} + diff --git a/spo256/spo256.8 b/spo256/spo256.8 new file mode 100644 index 0000000..a0826ad --- /dev/null +++ b/spo256/spo256.8 @@ -0,0 +1,98 @@ +.TH "spo256" "8" "January 1997" "Speak 0.2" "Text-to-Speech" +.PP +.SH NAME +.PP +\fBspo256\fP - text-to-speech server for SPO256-AL2 chipset. +.PP +.SH SYNOPSIS +.PP +\fBspo256\fP +.PP +.SH DESCRIPTION +.PP +The \fBspo256\fP server provides a TCP/IP service interface for controlling +a serial based SPO256-AL2 text-to-speech chip. The server binds to the +"\fIspeak\fP" port defined in /etc/services and attaches to the serial +tty device specified in the [\fIinterface\fP] section of \fBspeak.conf\fP. +The server accepts a single TCP session from a client application at a time, +streaming that client's text to the SPO device. The server corrects +pronunciation of words, numbers, and common usages by performing in-stream +text substitution before sending output to the SPO. +.PP +.SH INSTALLATION +.PP +The \fBspo256\fP server is meant to be started during system initialization +(usually for run level 3). A \fBspeak.init\fP script is installed into +/etc/rc.d, and this script will be linked to a numbered phase in the +/etc/rc3.d directory. This final linkage is now part of the 'make install' +supplied and should work for Linux, and perhaps other UNIX systems with +similar rc.d directory and file layouts. The \fBspo256\fP service can +normally start immediately after network services (\fIS10network\fP) have ran. +.PP +For BSD style systems, the speak.init script is installed as 'rc.speak'. For +systems that have different naming schemes for the rc.d scripts, some +additional work may be needed to correctly install speak.init. The +\fBspo256\fP server may also be ran directly from the command line For +testing, and the \fBspo256\fP command can simply be added to the +\fIrc.local\fP file. +.PP +The make install will add an entry to \fB/etc/services\fP for the TCP speak +port. By default, I normally use port 800. Since no effort has been made +to register text-to-speech as a defined Internet port service, it is quite +conceivable port 800 may at some point be defined for another service. If +this happens, simply edit the /etc/services file as needed. +.PP +The [\fIinterface\fP] section of \fB/etc/speak.conf\fP will need to be +edited before you start \fBspo256\fP for the first time. The entry for +\fIdevice\fP should be given the correct tty serial port where your SPO +board is attached. The speed I choose to use is 2400bps, which is the +maximum speed the board is capable of. Valid values for parity include +"odd", "even", and "none". Also verify board jumpers +are set for the speed and data format specified in [\fIinterface\fP]. +.PP +.SH "CORRECTIVE SPEECH" +.PP +The [\fIwords\fP] section of \fBspeak.conf\fP holds a list of text +substitutions. These substitutions correct the inability of the SPO to +correctly pronounce may words. Since the SPO provides no direct access +to the low-level phonetic dictionary, these substitute spellings may +appear odd. Sometimes, words are broken into multiple words with spaces, +such as "online", which is sent to the SPO as "on lyne". Basically, +through trial and error, one can build up a substitution table that works +for the device. +.PP +The [\fIabbrev\fP] section simply provides the meaning behind commonly +used abbreviations, so that they are spoken out correctly. Abbreviations +are presumed to terminate with a '.', such as "Dr.", "Mr.", and are +represented in a table separate from the text substitution table. +.PP +.SH SERVER COMMANDS +.PP +Server commands were introduced with the third release of the SPO256 +server. These commands are formed as "tags" which appear as part of the +output stream sent to the server. These tags are preceeded by the <ESC> +character, and are held in <>'s (much like HTML tags). Server commands +that are supported by different speech servers may very widly to support +features such as volume level, tone, inflection, etc. The limited set +of commands supported by the SPO server are as follows: +.PP +The <\fIecho\fP> and <\fI/echo\fP> tags may be used to turn echo on and +off. When echo is enabled, the output that is actually sent to the SPO +device (including corrected spellings) is also echo'd back to the client +that is connected to the server. +.PP +The <\fIspell\fP> and <\fI/spell\fP> tags may be used to turn spelling of +words on and off. In spelling mode, each letter of each word is spoken. +This should not be confused with <\fIlit\fP> and <\fI/lit\fP>, which are +used to disable the word lookup function so that text as actually sent +to the server is sent unprocessed to the SPO board. +.PP +.SH SEE ALSO +.PP +.BR speak.conf (7), +.BR services (7) +.PP +.SH AUTHOR +.PP +David Sugar (dyfet@tycho.com) +.PP diff --git a/spo256/word.c b/spo256/word.c new file mode 100644 index 0000000..2150837 --- /dev/null +++ b/spo256/word.c @@ -0,0 +1,38 @@ +/* + + Word base pronounciation rules and special cases. +*/ + +#include <ctype.h> +#include <std/types.h> +#include <std/string.h> +#include <std/config.h> +#include "speak.h" + +void word(char *str) +{ + char *p; + + /* Internet x@y as "x at y" */ + + if(NULL != (p = strchr(str, '@'))) + { + *(p++) = 0; + word(str); + word("at"); + word(p); + return; + } + + /* Check for x.y.z as "x dot y dot z" */ + + while(NULL != (p = strchr(str, '.'))) + { + *(p++) = 0; + spo_word(str); + spo_word("dot"); + str = p; + } + + spo_word(str); +} diff --git a/spo256/words.c b/spo256/words.c new file mode 100644 index 0000000..19c8d57 --- /dev/null +++ b/spo256/words.c @@ -0,0 +1,34 @@ +/* + + Each line of input from the client application is examined and split + into words, numbers, abbreviations, and special catagories for further + translation from free-form text to SPO spoken speech. Generally a + word is a collection of characters grouped by white-space markers + (nl, tab, and space). Special consideration is also given to quoting + properties. Additional rules may be applied once words have been + catagorized. +*/ + +#include <other/string.h> +#include <other/config.h> +#include <std/string.h> +#include "speak.h" + +void abbrev(char *str) +{ + char *p; + + if(!lit && !spell) + p = find(aidx, str); + + if(p) + spo_word(p); + else + { + p = tail(str); + *(--p) = 0; + spo_word(str); + spo_pause(P_SENTANCE); + } +} + diff --git a/utils/Makefile.in b/utils/Makefile.in new file mode 100644 index 0000000..8ff750c --- /dev/null +++ b/utils/Makefile.in @@ -0,0 +1,31 @@ +# +# Template to build speak utilities. +# $Id: Makefile.in 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ +# Copyright (c) 1997 by Tycho Softworks. +# + +UPROGS = say +SPROGS = down vmon +PROGS = $(SPROGS) $(UPROGS) + +all: $(PROGS) + +install: $(PROGS) + install -s -g bin $(UPROGS) $(BINDIR) + install -s -g bin $(SPROGS) $(SBINDIR) + ln -sf $(SBINDIR)/vmon $(SBINDIR)/vstat + ../sdk/bin/instman $(MANDIR) 1 say + ../sdk/bin/instman $(MANDIR) 8 down vmon + +clean: + rm $(PROGS) + +say: say.c + $(CC) $(CFLAGS) $(OPTIMIZE) -I../sdk -L../sdk/lib -o $@ say.c $(LIBS) + +down: down.c + $(CC) $(CFLAGS) $(OPTIMIZE) -I../sdk -L../sdk/lib -o $@ down.c $(LIBS) + +vmon: vmon.c + $(CC) $(CFLAGS) $(OPTIMIZE) -I../sdk -L../sdk/lib -o $@ vmon.c $(LIBS) + diff --git a/utils/README b/utils/README new file mode 100644 index 0000000..66d3435 --- /dev/null +++ b/utils/README @@ -0,0 +1,9 @@ +This section includes portable 'speak' service based utilities. These +utilities are being ported from the original WorldVU SPO speak services. So +far, only "say", "down", and "vmon" have been ported. Additional +utilities to be added will include a new non-WorldVU related user session +announcement daemon, perhaps as part of vmon. The original user session +monitoring utility was closely tied into the WorldVU user cluster +monitoring system. + + diff --git a/utils/down.8 b/utils/down.8 new file mode 100644 index 0000000..fe0b81d --- /dev/null +++ b/utils/down.8 @@ -0,0 +1,44 @@ +.TH "down" "8" "January 1997" "Speak 0.2" "Text-to-Speech" +.PP +.SH NAME +.PP +\fBdown\fP - warn and then shutdown system. +.PP +.SH SYNOPSIS +.PP +\fBdown\fP [\fIseconds\fP] +.PP +.SH DESCRIPTION +.PP +The Text-to-speech package introduces a standard TCP/IP port service for +attaching text-to-speech resources to your network. These resources can +be used to monitor system status, provide verbal alarms, etc. This network +service may be accessed by telnetting to a machine running a "speak" server, +or by using the various application utilities, such as \fBdown\fP. +.PP + +The \fBdown\fP program will provide a warning with a countdown that may +be aborted. When the countdown reaches 0, your system will begin a normal +shutdown and reboot. The warning and countdown is shown on screen and +spoken over the text-to-speech interface. The \fBdown\fP program uses the +[\fIdown\fP] information in \fBspeak.conf\fP for default values. Only an +alternate countdown (in seconds) may be specified via a command line +argument. + +.PP +The [\fIdown\fP] section specifies a default timer to use, the hostname +where the speech server is running, and the program to execute to bring +the system down. If you are using \fBdown\fP on a machine that does not +have it's own text-to-speech server, then you will need to create a local +\fB/etc/speak.conf\fP file on that machine with at minimum a [\fIdown\fP] +section with an entry for the text-to-speech host server to use. + +.PP +.SH SEE ALSO +.PP +.BR speak.conf (7) +.PP +.SH AUTHOR +.PP +David Sugar (dyfet@tycho.com) +.PP diff --git a/utils/down.c b/utils/down.c new file mode 100644 index 0000000..66d9d19 --- /dev/null +++ b/utils/down.c @@ -0,0 +1,129 @@ +/* + * A verbal system shutdown utility. + * $Id: down.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions of distribution and reuse see product license. + * + * Abstract: + * A verbal system shutdown utility. You may need to adjust the name + * of the shutdown program used. This gives some warning and then + * initiates the shutdown processing, unless cancelled in time. + */ + +#include <std/signal.h> +#include <proc/process.h> +#include <other/string.h> +#include <std/files.h> +#include <other/config.h> +#include <net/stream.h> + +static char host[128] = "localhost"; +static char halt[60] = "/sbin/halt"; +static char abort_msg[] = "System shutdown overriden. Resuming normal operation.\n"; +static char down_msg[] = "%s system shutdown sequence initiated. You have %d seconds to override.\n"; +static int timer = 10; +static STREAM fp = NULL; + +/* + * If the user aborts the shutdown, then we send the cancellation message + * and gracefully exit the scene. + */ + +static void abort_sig() +{ + if(fp) + { + puttcp(abort_msg, fp); + closetcp(fp); + } + fputs("\n", stdout); + exit(-1); +} + +void main(int argc, char **argv) +{ + char *p; + char *reboot = halt; + int port = getservice("speak"); + CONFIG *cfg = sys_config("speak"); + char hostname[128]; + + if(argc < 1 || argc > 2) + fatal(EX_USAGE, "use: down [timer]\n"); + + if(!port) + fatal(EX_UNAVAILABLE, "down: speak: service unlisted in /etc/services\n"); + + if(!cfg) + fatal(EX_CONFIG, "down: speak.conf: config missing\n"); + + seek_config(cfg, "down"); + while(read_config(cfg)) + { + if(NULL != (p = get_config(cfg, "timer"))) + { + timer = atoi(p); + continue; + } + + if(NULL != (p = get_config(cfg, "halt"))) + { + strcpy(halt, p); + continue; + } + + if(NULL != (p = get_config(cfg, "host"))) + { + strcpy(host, p); + continue; + } + + if(NULL != (p = get_config(cfg, "server"))) + { + strcpy(host, p); + continue; + } + } + close_config(cfg); + if(argc > 1) + timer = atoi(argv[1]); + + fp = opentcp(host, port); + if(!fp) + fatal(EX_UNAVAILABLE, "down: %s: speak service unreachable\n", host); + + printf("System shutdown initiated...use <break> to override; "); + fflush(stdout); + signal(SIGINT, abort_sig); + gettcp(hostname, 127, fp); + gethostname(hostname, 80); + fprintf(fp, down_msg, hostname, timer); + fflush(fp); + sleep(strlen(down_msg) / 9 + 1); + + /* count down timer until 0 */ + + while(timer) + { + printf("%d ", timer); + fflush(stdout); + fprintf(fp, "%d\n", timer); + fflush(fp); + sleep(1); + --timer; + } + + /* too late now!! */ + + signal(SIGINT, SIG_IGN); + printf("\n"); + closetcp(fp); + + /* detach return to user and execute reboot program */ + + pdetach(D_KEEPALL); + argv[0] = reboot; + argv[1] = NULL; + execvp(reboot, argv); +} + diff --git a/utils/say.1 b/utils/say.1 new file mode 100644 index 0000000..1807b76 --- /dev/null +++ b/utils/say.1 @@ -0,0 +1,35 @@ +.TH "say" "1" "January 1997" "Speak 0.2" "Text-to-Speech" +.PP +.SH NAME +.PP +\fBsay\fP - send output string to text-to-speech service. +.PP +.SH SYNOPSIS +.PP +\fBspeak\fP \fIhostname\fP "\fImessage\fP" +.PP +.SH DESCRIPTION +.PP +The Text-to-speech package introduces a standard TCP/IP port service for +attaching text-to-speech resources to your network. These resources can +be used to monitor system status, provide verbal alarms, etc. This network +service may be accessed by telnetting to a machine running a "speak" server, +or by using the various application utilities, such as \fBsay\fP. +.PP + +The \fBsay\fP program will send a specified string of text to a specified +network speech server. The intent is to use say to produce verbal output +much like the way "echo" may be used to create screen output. \fBsay\fP +will form a momentary connection with the speech server (such as +\fBspo256\fP), send the message, and then disconnect. The TCP +service port used for the connection is specified in \fI/etc/services\fP. + +.PP +.SH SEE ALSO +.PP +.BR speak (1) +.PP +.SH AUTHOR +.PP +David Sugar (dyfet@tycho.com) +.PP diff --git a/utils/say.c b/utils/say.c new file mode 100644 index 0000000..b774eaf --- /dev/null +++ b/utils/say.c @@ -0,0 +1,34 @@ +/* + * Send text to speech server. May be used in script files. + * $Id: say.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions on distribution and reuse see product license. + */ + +#include <std/string.h> +#include <std/process.h> +#include <net/stream.h> + +void main(int argc, char **argv) +{ + STREAM fp; + int port = getservice("speak"); + char buf[128]; + + if(argc != 3) + fatal(EX_USAGE, "use: say host \"message\"\n"); + + if(!port) + fatal(EX_UNAVAILABLE, "say: speak: service not in /etc/services\n"); + + fp = opentcp(argv[1], port); + if(!fp) + fatal(EX_UNAVAILABLE, "say: %s: speak service unavailable\n", argv[1]); + + gettcp(buf, 127, fp); + puttcp(argv[2], fp); + puttcp("\n", fp); + closetcp(fp); +} + + diff --git a/utils/vmon.8 b/utils/vmon.8 new file mode 100644 index 0000000..84a1308 --- /dev/null +++ b/utils/vmon.8 @@ -0,0 +1,65 @@ +.TH "vmon" "8" "January 1997" "Speak 0.2" "Text-to-Speech" +.PP +.SH NAME +.PP +\fBvmon\fP - monitor system status (town crier). +.PP +.SH SYNOPSIS +.PP +\fBvmon\fP \fIfilesystems\fP +.br +\fBvstat\fP \fIfilesystems\fP +.PP +.SH DESCRIPTION +.PP +The Text-to-speech package introduces a standard TCP/IP port service for +attaching text-to-speech resources to your network. These resources can +be used to monitor system status, provide verbal alarms, etc. This network +service may be accessed by telnetting to a machine running a "speak" server, +or by using the various application utilities, such as \fBvmon\fP. +.PP + +The \fBvmon\fP program will monitor the specified list of file systems. +If any of these file systems exceed a maximum "quota" (such as over 90% +capacity in blocks or i-node use), then the monitor will send verbal +alerts every 5 minutes. This quota, and other parameters for vmon, may +be found in the [\fIvmon\fP] section of \fBspeak.conf\fP. +.PP + +The \fBvmon\fP program will also announce current system status once +every hour. This system status includes the total used capacity of +all file systems being monitored, how long the system has been up, and +how many users are currently logged in (excluding root). This hourly +announcement can be used to determine a given system is still alive. +.PP + +The \fBvmon\fP program will now also monitor specified user mailboxes +for new mail and announce when new mail arrives. The users to be +monitored are specified in the [\fIvmon\fP] section of \fBspeak.conf\fP. +Simply list mailbox= entries for each mailbox you wish to monitor. See +the example speak.conf included with the distribution. +.PP + +The \fBvmon\fP program can also be ran as \fBvstat\fP. When used as +\fBvstat\fP, the program performs an immediate system check, announces, +and then terminates. You can either use \fBvstat\fP from a crontab or +start \fBvmon\fP from \fBspeak.init\fP. You may also start \fBvmon\fP +from a \fBrc.local\fP file. Please check the \fBspeak.init\fP file +to add any file systems you wish to monitor. By default, the root +filesystem is enabled in \fBspeak.init\fP. +.PP + +A mute option may also be specified in the [\fIvmon\fP] section of +\fBspeak.conf\fP. This option mutes voice output during certain times of +the day. This is normally specified by 24 hour clock in hours, hence 18-7 +means to mute output anytime after 18' hours (6pm) and anytime before 7' +hours (7am). +.PP +.SH SEE ALSO +.PP +.BR speak.conf (7) +.PP +.SH AUTHOR +.PP +David Sugar (dyfet@tycho.com) +.PP diff --git a/utils/vmon.c b/utils/vmon.c new file mode 100644 index 0000000..e1015b4 --- /dev/null +++ b/utils/vmon.c @@ -0,0 +1,442 @@ +/* Verbal monitor system status. + * $Id: vmon.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ + * Copyright (c) 1997 by Tycho Softworks. + * For conditions on distribution and reuse see product license. + * + * Abstract: + * Monitor system status in background. This service is normally + * started with the speech server. It may also be ran as 'vstat' + * to perform immediate notification. + */ + +#include <std/time.h> +#include <other/string.h> +#include <proc/process.h> +#include <other/config.h> +#include <net/stream.h> +#include <std/utmp.h> + +/* For systems that use statfs! */ + +#ifdef __linux__ +#include <sys/vfs.h> +#define __statfs__ +#endif + +typedef struct _MAILBOX +{ + struct _MAILBOX *next; + time_t update; + ulong size; + char name[0]; +} MAILBOX; + +static int freq = 3600; +static int timer = 3600; +static int interval = 300; +static int iter; +static int orig_timer; +static int alert = 90; /* warn on 90% full */ +static char alertmsg[] = "emergency alert emergency alert \r\n"; +static char **fs; +static char host[128] = "localhost"; +static int mute[2] = {24, 0}; + +static char *vmailbox(MAILBOX *mbox) +{ + struct stat ino; + static char buf[80]; + + if(stat(mbox->name, &ino)) + return NULL; + + if(!ino.st_size) + { + mbox->size = 0; + return NULL; + } + + if(ino.st_size == mbox->size) + return NULL; + + if(mbox->size == -1) + { + mbox->size = ino.st_size; + return NULL; + } + + mbox->size = ino.st_size; + sprintf(buf, "User %s has new mail\n", mbox->name); + return buf; +} + +static void vmbox(MAILBOX *box, int port) +{ + STREAM fp = NULL; + char *p; + time_t now; + struct tm *dt; + char buf[128]; + + time(&now); + dt = localtime(&now); + if(dt->tm_hour > mute[0] || dt->tm_hour < mute[1]) + return; + + while(box) + { + p = vmailbox(box); + if(!p) + { + box = box->next; + continue; + } + if(!fp) + { + fp = opentcp(host, port); + if(!fp) + return; + + gettcp(buf, sizeof(buf) - 1, fp); + } + puttcp(p, fp); + box = box->next; + } + if(fp) + closetcp(fp); +} + +static int vstat(int port) +{ + int i = 0; + char *f; + long btotal = 0; + long bfree = 0; + bool failed = FALSE; + STREAM fp = NULL; +#ifdef __statfs__ + struct statfs fnode; +#endif + int blocks, inodes; + char buf[128]; + int newtimer = orig_timer; + time_t now; + static prior = -1; + struct tm *dt; + int apm, hour; + char *apmstr[] = {" A M ", " P M "}; + int fd; + struct utmp *utmp, uptime; + int users = 0; + int utcnt = 0; + +#ifdef __statfs__ + while(fs[i]) + { + if(!statfs(fs[i], &fnode)) + { + btotal += fnode.f_blocks; + bfree += fnode.f_bfree; + blocks = 100 - (int)(fnode.f_ffree / (fnode.f_files / 100l)); + inodes = 100 - (int)(fnode.f_bfree / (fnode.f_blocks / 100l)); + if((blocks < alert) && (inodes < alert)) + { + ++i; + continue; + } + } + else + { + inodes = 0; + blocks = 0; + failed = TRUE; + } + if(!fp) + { + fp = opentcp(host, port); + if(!fp) + { + newtimer = 300; + break; + } + gettcp(buf, 128, fp); + puttcp(alertmsg, fp); + } + + if(blocks > alert) + fprintf(fp, "File system %s is %d percent full.\r\n", fs[i], blocks); + + if(inodes > alert) + fprintf(fp, "File system %s i-node table is %d percent full.\r\n", fs[i], inodes); + + if(failed) + fprintf(fp, "File system %s is dismounted or failed\r\n", fs[i]); + + fflush(fp); + newtimer = 60; + ++i; + } +#endif + + if(fp) + closetcp(fp); + + time(&now); + if(prior == (now / freq)) + return newtimer; + + if(prior == -1) + prior = now / freq - 1; + else + prior = now / freq; + + dt = localtime(&now); + hour = dt->tm_hour % 12; + if(dt->tm_hour > mute[0] || dt->tm_hour < mute[1]) + return newtimer; + + if(!hour) + hour = 12; + + if(dt->tm_hour > 11) + apm = 1; + else + apm = 0; + + fp = opentcp(host, port); + if(!fp) + return newtimer; + + gettcp(buf, 128, fp); + fprintf(fp, "It is %d:%d %s \r\n", hour, dt->tm_min, apmstr[apm]); + fflush(fp); + + fd = open("/proc/uptime", O_RDONLY); + hour = -1; + if(fd > -1) + { + read(fd, buf, 128); + close(fd); + hour = atol(buf) / 3600; + } + +#if defined(BOOT_TIME) || defined(RUN_LVL) + if(hour == -1) + { + utmp = NULL; + memset(&uptime, 0, sizeof(uptime)); +#ifdef BOOT_TIME + setutent(); + uptime.ut_type = BOOT_TIME; + utmp = getutid(&uptime); +#endif +#ifdef RUN_LVL + if(!utmp) + { + setutent(); + uptime.ut_type = RUN_LVL; + utmp = getutid(&uptime); + } +#endif + if(utmp) + hour = (now - utmp->ut_time) / 3600l; + + endutent(); + } +#endif + + if(hour > -1) + { + if(hour == 1) + fprintf(fp, "The system has been up 1 hour\r\n"); + else if(hour < 48) + fprintf(fp, "The system has been up %d hours\r\n", hour); + else + fprintf(fp, "The system has been up %d days\r\n", hour / 24); + fflush(fp); + } + + setutent(); + while(NULL != (utmp = getutent())) + { + ++utcnt; + +#ifdef USER_PROCESS + if(utmp->ut_type != USER_PROCESS) + continue; +#endif + + utmp->ut_user[sizeof(utmp->ut_user)] = 0; + if(!strcmp(utmp->ut_user, "root")) + continue; + + if(!utmp->ut_user[0]) + continue; + + if(!utmp->ut_line[0]) + continue; + +#ifdef USER_PROCESS + if(kill(utmp->ut_pid, 0)) + continue; +#endif + + ++users; + } + endutent(); + + if(utcnt) + { + if(!users) + fprintf(fp, "There are no users online\r\n"); + else if(users == 1) + fprintf(fp, "There is 1 user online\r\n"); + else + fprintf(fp, "There are %d users online\r\n", users); + fflush(fp); + } + + if(btotal) + { + fprintf(fp, "The main system drives are at %d percent of capacity\r\n", + 100 - (int)(bfree / (btotal / 100))); + fflush(fp); + } + + closetcp(fp); + return newtimer; +} + +void main(int argc, char **argv) +{ + int port = getservice("speak"); + char *maildir = getenv("MAILDIR"); + MAILBOX *mbox = NULL, *newbox; + char *prog = basename(*argv); + CONFIG *cfg = sys_config("speak"); + time_t now; + char *p; + + if(argc < 2) + fatal(EX_USAGE, "use %s filesystems...\n", prog); + + if(!maildir) + maildir = "/var/spool/mail"; + + fs = ++argv; + + if(!port) + fatal(EX_UNAVAILABLE, "%s: speak: service unavailable\n", prog); + + if(!cfg) + fatal(EX_UNAVAILABLE, "%s: speak.conf: missing\n", prog); + + seek_config(cfg, "vmon"); + while(read_config(cfg)) + { + if(NULL != (p = get_config(cfg, "mailbox"))) + { + p = strtok(p, __SPACES); + while(p) + { + newbox = (MAILBOX *)malloc(sizeof(MAILBOX) + strlen(p) + 1); + newbox->next = mbox; + time(&newbox->update); + newbox->size = -1l; + strcpy(newbox->name, p); + mbox = newbox; + p = strtok(NULL, __SPACES); + } + continue; + } + + if(NULL != (p = get_config(cfg, "interval"))) + { + interval = atoi(p) * 60; + continue; + } + + if(NULL != (p = get_config(cfg, "frequency"))) + { + timer = 3600 / atoi(p); + continue; + } + + if(NULL != (p = get_config(cfg, "server"))) + { + strcpy(host, p); + continue; + } + + if(NULL != (p = get_config(cfg, "host"))) + { + strcpy(host, p); + continue; + } + + if(NULL != (p = get_config(cfg, "alert"))) + { + alert = atoi(p); + continue; + } + + if(NULL != (p = get_config(cfg, "timer"))) + { + timer = atoi(p) * 60; + continue; + } + + if(NULL != (p = get_config(cfg, "mute"))) + { + mute[0] = atoi(p); + p = strchr(p, '-'); + if(p) + mute[1] = atoi(strtrim(++p, __SPACES)); + continue; + } + + if(NULL != (p = get_config(cfg, "maildir"))) + { + maildir = strdup(p); + continue; + } + + } + close_config(cfg); + + if(stricmp(prog, "vmon")) + { + vstat(port); + exit(0); + } + + pdetach(D_KEEPNONE); + + chdir(maildir); + freq = timer; + orig_timer = timer; + time(&now); + for(;;) + { + timer = vstat(port); + iter = interval; + for(;;) + { + vmbox(mbox, port); + sleep(iter); + time(&now); + iter = timer - (now % timer) - 1; + + if(iter > interval) + iter = interval; + + if(iter < 2) + { + sleep(iter + 2); + break; + } + } + } +} + + |