[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Axiom-developer] 20070822.01.tpd.patch applied to silver
From: |
daly |
Subject: |
[Axiom-developer] 20070822.01.tpd.patch applied to silver |
Date: |
Mon, 27 Aug 2007 02:41:38 -0500 |
diff --git a/changelog b/changelog
index 282bd89..180fc5c 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,4 @@
+20070821 tpd src/sman/bookvol6 document the axiom shell script
20070821 tpd src/sman/bookvol6 add axiom command
20070821 tpd src/sman/Makefile add axiom command
20070821 tpd src/etc/axiom remove axiom command
diff --git a/src/sman/bookvol6.pamphlet b/src/sman/bookvol6.pamphlet
index ade0c54..d80388b 100644
--- a/src/sman/bookvol6.pamphlet
+++ b/src/sman/bookvol6.pamphlet
@@ -25,47 +25,50 @@ $$
\center{\large{VOLUME 6: AXIOM COMMAND}}
\end{titlepage}
\pagenumbering{roman}
-\begin{verbatim}
+
Portions Copyright (c) 2005 Timothy Daly
The Blue Bayou image Copyright (c) 2004 Jocelyn Guidry
Portions Copyright (c) 2004 Martin Dunstan
-Portions Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
-All rights reserved.
+Portions Copyright (c) 1991-2002, The Numerical ALgorithms Group
+Ltd. All rights reserved.
This book and the Axiom software is licensed as follows:
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - 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.
-
- - Neither the name of The Numerical ALgorithms Group Ltd. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
-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.
-
-\end{verbatim}
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following
+conditions are met:
+\begin{itemize}
+\item Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+
+\item 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.
+
+\item Neither the name of The Numerical ALgorithms Group Ltd. nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+\end{itemize}
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
Inclusion of names in the list of credits is based on historical
information and is as accurate as possible. Inclusion of names
@@ -194,86 +197,408 @@ November 10, 2003 ((iHy))
\pagenumbering{arabic}
\setcounter{chapter}{0} % Chapter 1
\chapter{Overview}
-The superman process, called sman, is normally invoked from the
-axiom shell script in order to start a tree of subprocesses.
+The axiom system consists of a set of processes managed by the
+superman process. The superman process, called sman, is normally
+invoked from the axiom shell script in order to start a tree of
+subprocesses.
+
+The {\tt axiom} command is a shell script that collects the
+command line options for the {\tt sman} process, sets some shell
+variables, and then invokes {\tt sman}.
+
+The {\tt sman} process starts the following tree of processes:
+\begin{verbatim}
+ --xterm---bash---sman-|-AXIOMsys
+ |-clef---spadclient
+ |-hypertex
+ |-session
+ |-sman
+ |-viewman
+\end{verbatim}
\chapter{The axiom Command}
+The {\tt axiom} command starts everything for Axiom. The options
+for the {\tt axiom} command are:
+\begin{verbatim}
+axiom
+ [-ht |-noht] whether to use HyperDoc
+ [-gr |-nogr] whether to use Graphics
+ [-clef |-noclef] whether to use Clef
+ [-nonag |-nag] whether to use NAG
+ [-noiw |-iw] start in interpreter in a separate window
+ [-ihere |-noihere] start an interpreter in this window
+ [-nox] don't use X Windows
+ [-go |-nogo] whether to start system
+ [-ws wsname] use named workspace
+ [-list] list workspaces only
+ [-grprog fname] use named program for Graphics
+ [-nagprog fname] use named program for Nag
+ [-htprog fname] use named program for HyperDoc
+ [-clefprog fname] use named program for Clef
+ [-sessionprog fname] use named program for session
+ [-clientprog fname] use named program for spadclient
+ [-h] show usage
+\end{verbatim}
+
+In detail, the command options are:
+\subsection{[-ht $\vert$ -noht]}
+\begin{verbatim}
+ [-ht |-noht] whether to use HyperDoc
+\end{verbatim}
+{\tt Hyperdoc}\cite{7} is the documentation tool for Axiom. The
+{\tt -ht} option, enabled by default, will start this tool.
+See Jenks\cite{1} Chapter 3 for further information on the
+{\tt hyperdoc} subsystem.
+
+\subsection{[-gr $\vert$ -nogr]}
+\begin{verbatim}
+ [-gr |-nogr] whether to use Graphics
+\end{verbatim}
+The {\tt graphics}\cite{8} subsystem is enabled using the
+{\tt -gr} option, enabled by default. Graphics will appear as a
+result of a draw command, such as
+\begin{verbatim}
+ draw(sin(x),x=0..1)
+\end{verbatim}
+Note that attempting to use draw commands when the graphics is
+disabled will simply hang the interpreter waiting for a response.
+See Jenks\cite{1} Chapter 7 for further information on the
+{\tt graphics} subsystem.
+
+\subsection{[-clef $\vert$ -noclef]}
+\begin{verbatim}
+ [-clef |-noclef] whether to use Clef
+\end{verbatim}
+The {\tt clef} (Command Line Edit Facility) allows for command completion.
+The list of command completion strings is in the last chapter of this
+document. If {\tt clef}, enabled by default, is running then you can type:
+\begin{verbatim}
+ x:Dena<tab>
+\end{verbatim}
+and this will automatically be expanded to:
+\begin{verbatim}
+ x:DenavitHartenbergMatrix
+\end{verbatim}
+
+The {\tt clef} program also allows command line editing. The commands are
+special keyboard keys.
+\begin{itemize}
+\item HOME move to beginning of the line
+\item END move to the end of the line
+\item CTRL-END delete to end of the line
+\item TAB command completion (multiple tabs give new choices)
+\item UPARROW move back thru commands
+\item DOWNARROW move forward thru commands
+\item LEFTARROW move left on the line
+\item RIGHTARROW move right on the line
+\item INSERT toggle insert/overstrike
+\end{itemize}
+See Jenks\cite{1} page 21 for further information on the {\tt clef} command.
+
+\subsection{[-nonag $\vert$ -nag]}
+\begin{verbatim}
+ [-nonag |-nag] whether to use NAG
+\end{verbatim}
+The {\tt nag} option, disabled by default, will attempt to start
+the {\tt nagman} program in the \$AXIOM/lib subdirectory. Since
+the open source version does not include the NAG numeric libraries
+this option does not work.
+
+\subsection{[-noiw $\vert$ -iw]}
+\begin{verbatim}
+ [-noiw |-iw] start in interpreter in a separate window
+\end{verbatim}
+The {\tt iw} option, disabled by default, will start a second
+interpreter in its own window with its own frame. The fact that
+the second interpreter is in its own frame can be seen using the
+{\tt )frame} command. For instance, if you type
+\begin{verbatim}
+ axiom -iw
+\end{verbatim}
+there will be two interpreter windows available, one in the current
+window and one in a new window. In the current window if you type:
+\begin{verbatim}
+ )frame names
+\end{verbatim}
+you will see:
+\begin{verbatim}
+ The names of the existing frames are:
+ frame0
+ frame1
+ initial
+ The current frame is the first one listed.
+\end{verbatim}
+
+In the second window, if you type
+\begin{verbatim}
+ )frame names
+\end{verbatim}
+you will see:
+\begin{verbatim}
+ The names of the existing frames are:
+ frame1
+ frame0
+ initial
+ The current frame is the first one listed.
+\end{verbatim}
+Setting
+\begin{verbatim}
+ x:=3
+\end{verbatim}
+in the second window will set the variable $x$ in the frame {\tt frame1}.
+Switching to the first window and typing:
+\begin{verbatim}
+ x
+\end{verbatim}
+gives:
+\begin{verbatim}
+
+ (1) x
+ Type: Variable x
+\end{verbatim}
+since the first window is in {\tt frame0} and the variable $x$ is
+defined in {\tt frame1}.
+But we can switch frames in the first window using
+\begin{verbatim}
+ )frame next
+\end{verbatim}
+and then
+\begin{verbatim}
+ x
+\end{verbatim}
+gives:
+\begin{verbatim}
+
+ (2) 3
+ Type: PositiveInteger
+\end{verbatim}
+and now the two windows share the same frame space.
+See Jenks\cite{1} page 579 for further information on the {\tt frame} command.
+
+\subsection{[-ihere $\vert$ -noihere]}
+\begin{verbatim}
+ [-ihere |-noihere] start an interpreter in this window
+\end{verbatim}
+This option determines whether Axiom will start in the current window.
+Using this option alone is not particularly useful and it is generally
+used in combination with the {\tt -iw} option:
+\begin{verbatim}
+ axiom -noihere -iw &
+\end{verbatim}
+
+However, used alone, as in:
+\begin{verbatim}
+ axiom -noihere &
+\end{verbatim}
+it will start Axiom and show the Hyperdoc window. Graphics will also
+work from the Hyperdoc pages.
+
+\subsection{[-nox]}
+\begin{verbatim}
+ [-nox] don't use X Windows
+\end{verbatim}
+allows Axiom to start the interpreter without Hyperdoc or the graphics
+subsystem. This is useful for starting Axiom in an emacs buffer.
+
+\subsection{[-go $\vert$ -nogo]}
+\begin{verbatim}
+ [-go |-nogo] whether to start system
+\end{verbatim}
+uses the {\tt -go} option, enabled by default, controls whether
+the system starts from the command line. If the {\tt -nogo}
+option is chosen the system prints the command line that would
+have been issued. This is useful for finding out what the command
+line options to {\tt sman} will be. For instance:
+\begin{verbatim}
+ axiom -nogo -iw
+\end{verbatim}
+does not start Axiom but types out:
+\begin{verbatim}
+Would now start the processes.
+exec ~/mnt/linux/bin/sman -iw -ws ~/mnt/linux/bin/AXIOMsys
+\end{verbatim}
+
+\subsection{[-ws wsname]}
+\begin{verbatim}
+ [-ws wsname] use named workspace
+\end{verbatim}
+In the {\tt -nogo} command above you can see that the default
+workspace name is
+\begin{verbatim}
+-ws ~/mnt/linux/bin/AXIOMsys
+\end{verbatim}
+This option allows you to change that. This is useful for
+debugging new system builds. During build a debugging version
+of Axiom is created in the {\tt obj/linux/bin} directory. The
+{\tt debugsys} image uses interpreted lisp code rather than
+compiled code. This makes it possible to do deep debugging. To
+use this workspace you would incant:
+\begin{verbatim}
+ cd youraxiombuild
+ export AXIOM=`pwd`/mnt/linux
+ export PATH=$AXIOM/bin:$PATH
+ axiom -ws obj/linux/bin/debugsys
+\end{verbatim}
+
+
+\subsection{[-list]}
+\begin{verbatim}
+ [-list] list workspaces only
+\end{verbatim}
+shows you the executable workspaces. Generally in a built system
+there is only one, called\\
+{\tt \$AXIOM/bin/AXIOMsys}.
+
+\subsection{[-grprog fname]}
+\begin{verbatim}
+ [-grprog fname] use named program for Graphics
+\end{verbatim}
+allows you to specify which program to use for the graphics.
+By default this is\\
+{\tt \$AXIOM/lib/viewman}.
+
+\subsection{[-nagprog fname]}
+\begin{verbatim}
+ [-nagprog fname] use named program for Nag
+\end{verbatim}
+allows you to specify which program to use for the NAG library
+connection. By default this is\\
+{\tt \$AXIOM/lib/nagman} but it is disabled by default.
+
+\subsection{[-htprog fname]}
+\begin{verbatim}
+ [-htprog fname] use named program for Hyperdoc
+\end{verbatim}
+allows you tp specify which program to use for Hyperdoc. By
+default it is\\
+{\tt \$AXIOM/bin/hypertex -s}.
+
+\subsection{[-clefprog fname]}
+\begin{verbatim}
+ [-clefprog fname] use named program for Clef
+\end{verbatim}
+allows you to specify which program to use for clef. By default
+it is\\
+{\tt \$AXIOM/bin/clef -f \$AXIOM/lib/command.list -e}.
+
+\subsection{[-sessionprog fname]}
+\begin{verbatim}
+ [-sessionprog fname] use named program for session
+\end{verbatim}
+allows you to specify the session manager program. By default it is\\
+{\tt \$AXIOM/lib/session}.
+
+\subsection{[-clientprog fname]}
+\begin{verbatim}
+ [-clientprog fname] use named program for spadclient
+\end{verbatim}
+allows you to specify the spadclient program. By default it is\\
+{\tt \$AXIOM/lib/spadclient}.
+
+\subsection{[-h]}
+\begin{verbatim}
+ [-h] show usage
+\end{verbatim}
+
<<axiomcmd>>=
#!/bin/sh
-# Start everything for Axiom.
-#
-# axiom
-# [-ht |-noht] whether to use HyperDoc
-# [-gr |-nogr] whether to use Graphics
-# [-clef |-noclef] whether to use Clef
-# [-nag |-nonag] whether to use NAG
-# [-iw |-noiw] start in interpreter window
-# [-ihere|-noihere] start an interpreter buffer in the original window
-# [-nox] don't use X Windows
-# [-go |-nogo] whether to start system
-# [-ws wsname] use named workspace
-# [-list] list workspaces only
-# [-grprog fname] use named program for Graphics
-# [-nagprog fname] use named program for Nag
-# [-htprog fname] use named program for HyperDoc
-# [-clefprog fname] use named program for Clef
-# [-sessionprog fname] use named program for session
-# [-clientprog fname] use named program for spadclient
-# [-h] show usage
-#
-#
+@
+The {\tt MALLOCTYPE} shell variable is an {\tt IBM} {\tt AIX}
+shell variable that controls buckets based extensions in the default
+memory allocator which may enhance performance. AIX uses a new
+memory management routine that does not zero {\tt malloc} memory
+and does not round up to the nearest power of 2, unlike most non-AIX
+systems. This can cause failures so we protect against that here.
+See the AIX Performance Tuning Guide\cite{9} for details.
+<<axiomcmd>>=
MALLOCTYPE=3.1
export MALLOCTYPE
-# NAGMAN needs to know the hostname
+@
+The {\tt nagman} process needs to know the hostname
+<<axiomcmd>>=
HOST=`hostname`
export HOST
-# 0. Basic utilities
-
+@
+There are 4 basic utilities used by this script.
+The {\tt ciao} script for immediate exit:
+<<axiomcmd>>=
ciao() {
echo "Goodbye."
exit 1
}
+@
+The {\tt needsubopt} script which is used to issue an error message
+when one of the command line options requires an option:
+<<axiomcmd>>=
needsubopt () {
echo "The $1 option requires an argument."
ciao
}
-
-
+@
+The {\tt showuse} script which gives basic command line help:
+<<axiomcmd>>=
showuse() {
echo "axiom"
-echo " [-ht |-noht] whether to use HyperDoc"
-echo " [-gr |-nogr] whether to use Graphics"
-echo " [-clef |-noclef] whether to use Clef"
-echo " [-nag |-nonag] whether to use NAG"
-echo " [-iw |-noiw] start in interpreter window"
-echo " [-ihere|-noihere] start an interpreter buffer in the original
window."
-echo " [-nox] don't use X Windows"
-echo " [-go |-nogo] whether to start system"
-echo " [-ws wsname] use named workspace"
-echo " [-list] list workspaces only"
-#echo " [-grprog fname] use named program for Graphics"
-#echo " [-nagprog fname] use named program for Nag"
-#echo " [-htprog fname] use named program for HyperDoc"
-#echo " [-clefprog fname] use named program for Clef"
-#echo " [-sessionprog fname] use named program for session"
-#echo " [-clientprog fname] use named program for spadclient"
-echo " [-h] show usage"
+echo " [-ht |-noht] whether to use HyperDoc"
+echo " [-gr |-nogr] whether to use Graphics"
+echo " [-clef |-noclef] whether to use Clef"
+echo " [-nonag |-nag] whether to use NAG"
+echo " [-noiw |-iw] start in interpreter in a separate window"
+echo " [-ihere |-noihere] start an interpreter in this window"
+echo " [-nox] don't use X Windows"
+echo " [-go |-nogo] whether to start system"
+echo " [-ws wsname] use named workspace"
+echo " [-list] list workspaces only"
+echo " [-grprog fname] use named program for Graphics"
+echo " [-nagprog fname] use named program for Nag"
+echo " [-htprog fname] use named program for HyperDoc"
+echo " [-clefprog fname] use named program for Clef"
+echo " [-sessionprog fname] use named program for session"
+echo " [-clientprog fname] use named program for spadclient"
+echo " [-h] show usage"
}
-# 1. Ensure the environment is set.
+@
+List the various workspaces if asked.
+<<axiomcmd>>=
+listwspaces()
+{
+ echo "$1"
+ ls -l $2 | grep "sys$"
+ echo ""
+}
-# Just process '-h'
+@
+Step 1. Ensure the environment is set.
+
+Just process ``-h''. If it exists in the command line then we
+print out the simple command line help menu.
+<<axiomcmd>>=
if [ "$*" = "-h" ] ; then
showuse
fi
-SPADDEFAULT=/axiom/mnt/linux
+@
+We assume that Axiom is installed in the standard place on
+a linux system. We will modify this assumption as we process
+the environment and command line. The term {\tt spad} is an
+historical shortened version of the name {\tt scratchpad},
+the original name of the {\tt Axiom} system.
+<<axiomcmd>>=
+SPADDEFAULT=/usr/local/axiom/mnt/linux
+
+@
+If the {\tt \$AXIOM} shell variable is set then we use it.\\
+If not, then if the {\tt \$SPAD} shell variable is set then we use it.\\
+If not, then we try to use the default value above.\\
+If not, we simply fail.
+<<axiomcmd>>=
if [ "$SPAD" = "" ] ; then
if [ "$AXIOM" = "" ] ; then
SPAD=$SPADDEFAULT
@@ -300,6 +625,25 @@ else
fi
fi
+@
+If we get here then all attempts to find axiom have failed
+so we complain and exit.
+<<axiomcmd>>=
+if [ ! -d "$SPAD" ] ; then
+ echo "The directory for Axiom, $SPAD, does not exist."
+ ciao
+fi
+
+@
+If we get here we now
+know where axiom lives. We need to see if we can find the
+Aldor compiler. Aldor is optional and is not part of the open source
+version of Axiom due to license issues. However you can install it
+under the location specified by the {\tt \$AXIOMXLROOT} shell variable.
+If the compiler is found we add it to the {\tt PATH}.
+This shell variable defaults to the location:\\
+{\tt \$AXIOM/compiler}
+<<axiomcmd>>=
if [ "$AXIOMXLROOT" = "" ] ; then
AXIOMXLROOT=${AXIOM}/compiler
fi
@@ -307,97 +651,1182 @@ export AXIOMXLROOT
PATH=$AXIOM/bin:$AXIOMXLROOT/bin:${PATH}
export PATH
-
-
-if [ ! -d "$SPAD" ] ; then
- echo "The directory for Axiom, $SPAD, does not exist."
- ciao
-fi
-
-# Name the workspace directories.
+@
+Name the workspace directories.
+<<axiomcmd>>=
rootwsdir=$SPAD/bin
-# 2. Process command line arguments.
+@
+Step 2. Process command line arguments.
-# Defaults for command-line arguments.
+First we set up the defaults for command-line arguments.
+We don't want just a list by default
+<<axiomcmd>>=
list=no
+
+@
+We default to actually executing the workspace.
+<<axiomcmd>>=
go=yes
+
+@
+We default to the {\tt AXIOMsys} workspace.
+<<axiomcmd>>=
wsname=AXIOMsys
+@
+And all other options are unset.
+<<axiomcmd>>=
otheropts=""
+@
+For each option on the command line do
+<<axiomcmd>>=
while [ "$*" != "" ] ; do
+@
+<<axiomcmd>>=
case $1 in
+@
+If the user specified list anywhere then we give the workspace list
+and exit.
+<<axiomcmd>>=
+
-list) list=yes
go=no;;
+@
+If the user specified {\tt go} or {\tt nogo} we handle that case
+<<axiomcmd>>=
-go) go=yes ;;
-nogo) go=no ;;
+@
+The workspace option requires an argument which follows immediately.
+If the argument is missing we complain and exit.
+<<axiomcmd>>=
-ws)
if [ "$2" = "" ] ; then needsubopt "$1" ; fi
shift
wsname="$1"
;;
-
-nagprog|-grprog|-htprog|-clefprog|-sessionprog|-clientprog|-paste|-rm|-rv)
+@
+We can specify the various subprograms to use.
+<<axiomcmd>>=
+ -nagprog|-grprog|-htprog|-clefprog|-sessionprog|-clientprog)
if [ "$2" = "" ] ; then needsubopt "$1" ; fi
otheropts="$otheropts $1 $2"
shift
;;
-
-clef|-noclef|-gr|-nogr|-ht|-noht|-iw|-noiw|-ihere|-noihere|-nox|-nag|-nonag)
+@
+These options were not explained earlier and are only for developer use.
+<<axiomcmd>>=
+ -paste|-rm|-rv)
+ if [ "$2" = "" ] ; then needsubopt "$1" ; fi
+ otheropts="$otheropts $1 $2"
+ shift
+ ;;
+@
+We handle the various [{\tt -option} $\vert$ {\tt -nooption}] cases
+<<axiomcmd>>=
+ -clef|-noclef|-gr|-nogr|-ht|-noht|-iw|-noiw)
+ otheropts="$otheropts $1"
+ ;;
+ -ihere|-noihere|-nox|-nag|-nonag)
otheropts="$otheropts $1"
;;
-
+@
+The user wanted help so we will not execute.
+<<axiomcmd>>=
-h)
go=no
;;
-
-
+@
+The user is confused. Complain and exit.
+<<axiomcmd>>=
*) echo "Unknown option: $1"
echo "To use a specific workspace use, e.g.: spad -ws $1"
ciao
;;
esac
+@
+Move to the next option and loop.
+<<axiomcmd>>=
shift
done
-# 3. List the available workspaces, if asked
-
-listwspaces()
-{
- echo "$1"
- ls -l $2 | grep "sys$"
- echo ""
-}
+@
+Step 3. Handle options that require special case handling.
+The user just wanted to know what workspaces are available.
+<<axiomcmd>>=
if [ $list = yes ] ; then
- listwspaces "AXIOM workspaces in \$AXIOM/bin = $rootwsdir: "
$rootwsdir
+ listwspaces "AXIOM workspaces in \$AXIOM/bin = $rootwsdir: " $rootwsdir
fi
-# 5. Try to ensure a suitable workspace on this host.
-
+@
+Try to ensure a suitable workspace on this host.
+<<axiomcmd>>=
if [ `expr $wsname : '.*/.*'` = 0 ] ; then
serverws=$rootwsdir/$wsname
else
serverws=$wsname
fi
+@
+If we can't find the executable then we complain and exit.
+<<axiomcmd>>=
-if [ ! -f $serverws ] ; then
+if [ ! -x $serverws ] ; then
+ echo "Cannot find the executable $serverws"
showuse
ciao
fi
-
-# 6. Start processes
-
+@
+The user just wanted to see what would happen so we output the
+command line and exit.
+<<axiomcmd>>=
if [ $go = no ] ; then
echo "Would now start the processes."
echo exec $SPAD/bin/sman $otheropts -ws $serverws
exit 0
fi
-
+@
+All of the options have been processed so we start {\tt sman}
+<<axiomcmd>>=
exec $SPAD/bin/sman $otheropts -ws $serverws
+
+@
+\chapter{The {\tt sman} program}
+\section{sman.h}
+The spad\_proc structure holds information about the process id
+of a child process, what to do when it dies, and the shell command
+line necessary to restart the process. There is a linked list of
+these structures which maintains the process list for axiom.
+<<sman.h>>=
+/* Process control definitions. Used by fork_you and spawn_of_hell */
+
+/* When a process dies it kills off everything else */
+#define Die 1
+/* When a process dies, do nothing */
+#define NadaDelShitsky 2
+/* When a process dies start it up again */
+#define DoItAgain 3
+
+typedef struct spad_proc {
+ int proc_id; /* process id of child */
+ int death_action; /* one of the above constants */
+ char *command; /* sh command line to restart the process */
+ struct spad_proc *next;
+} SpadProcess;
+
+@
+\section{sman}
+\subsection{includes}
+<<sman.includes>>=
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#if defined(SUN4OS5platform) || defined(HP10platform)
+#include <sys/stropts.h>
+#endif
+
+#include "com.h"
+#include "bsdsignal.h"
+#include "sman.h"
+
+#include "bsdsignal.h1"
+#include "sockio-c.h1"
+#include "openpty.h1"
+#include "sman.h1"
+
+@
+\subsection{variables}
+<<sman.variables>>=
+char *ws_path; /* location of the AXIOM executable */
+int start_clef; /* start clef under spad */
+int start_graphics; /* start the viewman */
+int start_nagman; /* start the nagman */
+int start_ht; /* start hypertex */
+int start_spadclient; /* Start the client spad buffer */
+int start_local_spadclient; /* Start the client spad buffer */
+int use_X; /* Use the X windows environment */
+int server_num; /* AXIOM server number */
+@
+We add a debug flag so we can print information about what [[sman]]
+is trying to do. This change is pervasive as it touches nearly every
+routine.
+<<sman.variables>>=
+int tpd=0; /* to-print-debug information */
+
+/************************************************/
+/* definitions of programs which sman can start */
+/************************************************/
+
+<<the viewman command line>>
+<<the nagman command line>>
+<<the hypertex command line>>
+<<the clef command line>>
+<<the session manager command line>>
+<<the spadclient command line>>
+char *PasteFile = NULL;
+char *MakeRecordFile = NULL;
+char *VerifyRecordFile = NULL;
+
+SpadProcess *spad_process_list = NULL;
+/***************************/
+/* sman defaults file name */
+/***************************/
+
+#define SpadDefaultFile "spadprof.input"
+
+char ClefCommandLine[256];
+
+#define BufSize 4096 /* size of communication buffer */
+char big_bad_buf[BufSize]; /* big I/O buffer */
+
+Sock *session_io = NULL; /* socket connecting to session manager */
+
+/***********************************************************/
+/* Some characters used and externally defined in edible.h */
+/***********************************************************/
+
+unsigned char _INTR, _QUIT, _ERASE, _KILL, _EOF, _EOL, _RES1, _RES2;
+
+/*************************************/
+/* Stuff for opening pseudo-terminal */
+/*************************************/
+
+int ptsNum, ptcNum;
+char ptsPath[20], ptcPath[20];
+
+char **new_envp; /* new environment for AXIOM */
+int child_pid; /* child's process id */
+struct termios oldbuf; /* the original settings */
+struct termios childbuf; /* terminal structure for user i/o */
+
+int nagman_signal=0;
+int death_signal = 0;
+
+@
+\subsection{process\_arguments}
+<<sman.processarguments>>=
+static void
+process_arguments(int argc,char ** argv)
+{
+ int arg;
+ if (tpd == 1) fprintf(stderr,"sman:process_arguments entered\n");
+ for (arg = 1; arg < argc; arg++) {
+ if (strcmp(argv[arg], "-debug") == 0)
+ tpd = 1;
+ else if (strcmp(argv[arg], "-noclef") == 0)
+ start_clef = 0;
+ else if (strcmp(argv[arg], "-clef") == 0)
+ start_clef = 1;
+ else if (strcmp(argv[arg], "-gr") == 0)
+ start_graphics = 1;
+ else if (strcmp(argv[arg], "-nogr") == 0)
+ start_graphics = 0;
+ else if (strcmp(argv[arg], "-nag") == 0)
+ start_nagman = 1;
+ else if (strcmp(argv[arg], "-nonag") == 0)
+ start_nagman = 0;
+ else if (strcmp(argv[arg], "-ht") == 0)
+ start_ht = 1;
+ else if (strcmp(argv[arg], "-noht") == 0)
+ start_ht = 0;
+ else if (strcmp(argv[arg], "-iw") == 0)
+ start_spadclient = 1;
+ else if (strcmp(argv[arg], "-ihere") == 0)
+ start_local_spadclient = 1;
+ else if (strcmp(argv[arg], "-noihere") == 0)
+ start_local_spadclient = 0;
+ else if (strcmp(argv[arg], "-noiw") == 0)
+ start_spadclient = 0;
+ else if (strcmp(argv[arg], "-ws") == 0)
+ ws_path = argv[++arg];
+ else if (strcmp(argv[arg], "-comp") == 0)
+ ws_path = "$AXIOM/etc/images/comp";
+ else if (strcmp(argv[arg], "-nox") == 0)
+ {
+ use_X = 0;
+ start_local_spadclient = 1;
+ start_spadclient = 0;
+ start_ht = 0;
+ start_graphics = 0;
+ }
+ else if (strcmp(argv[arg], "-grprog") == 0)
+ GraphicsProgram = argv[++arg];
+ else if (strcmp(argv[arg], "-nagprog") == 0)
+ NagManagerProgram = argv[++arg];
+ else if (strcmp(argv[arg], "-htprog") == 0)
+ HypertexProgram = argv[++arg];
+ else if (strcmp(argv[arg], "-clefprog") == 0) {
+ strcpy(ClefCommandLine,argv[++arg]);
+ ClefProgram =
+ strcat(ClefCommandLine, " -f $AXIOM/lib/command.list -e ");
+ }
+ else if (strcmp(argv[arg], "-sessionprog") == 0)
+ SessionManagerProgram = argv[++arg];
+ else if (strcmp(argv[arg], "-clientprog") == 0)
+ SpadClientProgram = argv[++arg];
+ else if (strcmp(argv[arg], "-rm") == 0)
+ MakeRecordFile = argv[++arg];
+ else if (strcmp(argv[arg], "-rv") == 0)
+ VerifyRecordFile = argv[++arg];
+ else if (strcmp(argv[arg], "-paste") == 0)
+ PasteFile = argv[++arg];
+ else {
+ fprintf(stderr, "Usage: sman <-clef|-noclef> <-gr|-nogr> <-ht|-noht>");
+ fprintf(stderr, " <-iw|-noiw> <-nag|-nonag> <-nox> <-comp>");
+ fprintf(stderr, " <-ws spad_workspace> <-grprog path> <-htprog path>");
+ fprintf(stderr, " <-clefprog path> <-sessionprog path> <-nagprog path>");
+ fprintf(stderr, " <-clientprog path>\n");
+ exit(-1);
+ }
+ }
+ if (tpd == 1)
+ { fprintf(stderr," sman ");
+ if (start_clef == 0)
+ fprintf(stderr,"-noclef ");
+ else
+ fprintf(stderr,"-clef ");
+ if (start_graphics == 0)
+ fprintf(stderr,"-nogr ");
+ else
+ fprintf(stderr,"-gr ");
+ if (start_nagman == 0)
+ fprintf(stderr,"-nonag ");
+ else
+ fprintf(stderr,"-nag ");
+ if (start_ht == 0)
+ fprintf(stderr,"-noht ");
+ else
+ fprintf(stderr,"-ht ");
+ if (start_spadclient == 0)
+ fprintf(stderr,"-noiw ");
+ else
+ fprintf(stderr,"-iw ");
+ if (start_local_spadclient == 0)
+ fprintf(stderr,"-noihere ");
+ else
+ fprintf(stderr,"-ihere ");
+ if (start_local_spadclient == 0)
+ fprintf(stderr,"-noihere ");
+ else
+ fprintf(stderr,"-ihere ");
+ if (use_X == 0)
+ fprintf(stderr,"-nox ");
+ fprintf(stderr,"-ws ");
+ fprintf(stderr,"'%s' ",ws_path);
+ fprintf(stderr,"-grprog ");
+ fprintf(stderr,"'%s' ",GraphicsProgram);
+ fprintf(stderr,"-nagprog ");
+ fprintf(stderr,"'%s' ",NagManagerProgram);
+ fprintf(stderr,"-htprog ");
+ fprintf(stderr,"'%s' ",HypertexProgram);
+ fprintf(stderr,"-clefprog ");
+ fprintf(stderr,"'%s' ",ClefCommandLine);
+ fprintf(stderr,"-sessionprog ");
+ fprintf(stderr,"'%s' ",SessionManagerProgram);
+ fprintf(stderr,"-clientprog ");
+ fprintf(stderr,"'%s' ",SpadClientProgram);
+ fprintf(stderr,"-rm ");
+ fprintf(stderr,"'%s' ",MakeRecordFile);
+ fprintf(stderr,"-rv ");
+ fprintf(stderr,"'%s' ",VerifyRecordFile);
+ fprintf(stderr,"-paste ");
+ fprintf(stderr,"'%s' ",PasteFile);
+ fprintf(stderr,"\n");
+ }
+ if (tpd == 1) fprintf(stderr,"sman:process_arguments exit\n");
+}
+
+@
+\subsection{should\_I\_clef}
+<<sman.shouldIclef>>=
+static int
+should_I_clef(void)
+{
+ return(1);
+}
+
+@
+\subsection{in\_X}
+<<sman.inX>>=
+static int
+in_X(void)
+{
+ if (getenv("DISPLAY")) return 1;
+ return 0;
+}
+
+@
+\subsection{set\_up\_defaults}
+These are the default values for sman. A '1' value means that
+sman will try to start the given process, a '0' value means not
+starting the process.
+
+We do not have replacement code for the [[nagman]] process nor
+do we have a copy of the [[nag fortran library]] to test the process.
+Until this changes we set [[start_nagman = 0]] in order to disable
+starting this process by default.
+<<sman.setupdefaults>>=
+static void
+set_up_defaults(void)
+{
+ if (tpd == 1) fprintf(stderr,"sman:set_up_defaults entered\n");
+ start_clef = should_I_clef();
+ start_graphics = 1;
+ start_nagman = 0;
+ start_ht = 1;
+ start_spadclient = 0;
+ start_local_spadclient = 1;
+ use_X = isatty(0) && in_X();
+ ws_path = "$AXIOM/bin/AXIOMsys";
+ if (tpd == 1) fprintf(stderr,"sman:set_up_defaults exit\n");
+}
+
+@
+\subsection{process\_options}
+<<sman.processoptions>>=
+static void
+process_options(int argc, char **argv)
+{
+ if (tpd == 1) fprintf(stderr,"sman:process_options entered\n");
+ set_up_defaults();
+ process_arguments(argc, argv);
+ if (tpd == 1) fprintf(stderr,"sman:process_options exit\n");
+}
+
+@
+\subsection{death\_handler}
+<<sman.deathhandler>>=
+static void
+death_handler(int sig)
+{
+ death_signal = 1;
+}
+
+@
+\subsection{nagman\_handler}
+<<sman.nagmanhandler>>=
+static void
+nagman_handler(int sig)
+{
+ nagman_signal=1;
+}
+
+@
+\subsection{sman\_catch\_signals}
+<<sman.smancatchsignals>>=
+static void
+sman_catch_signals(void)
+{
+
+ /* Set up the signal handlers for sman */
+ bsdSignal(SIGINT, SIG_IGN,RestartSystemCalls);
+ bsdSignal(SIGTERM, death_handler,RestartSystemCalls);
+ bsdSignal(SIGQUIT, death_handler,RestartSystemCalls);
+ bsdSignal(SIGHUP, death_handler,RestartSystemCalls);
+ bsdSignal(SIGILL, death_handler,RestartSystemCalls);
+ bsdSignal(SIGTRAP, death_handler,RestartSystemCalls);
+ bsdSignal(SIGIOT, death_handler,RestartSystemCalls);
+ bsdSignal(SIGBUS, death_handler,RestartSystemCalls);
+ bsdSignal(SIGSEGV, death_handler,RestartSystemCalls);
+ /* don't restart wait call on SIGUSR1 */
+ bsdSignal(SIGUSR1, nagman_handler,DontRestartSystemCalls);
+ /* ONLY nagman should send this.
+ If an error (such as C-c) interrupts a NAGLINK call, nagman
+ gets a signal to clean up. We need to start another nagman
+ almost immediately to process the next NAGLINK request.
+ Since nagman takes a while to clean up, we treat it specially.
+ nagman should send a signal (USR1) to sman.
+ sman should respond by spawning a new nagman.
+
+ so nagman is NOT a DoItAgain but a NadaDelShitsky.
+
+ The USR1 mechanism does not work for HPUX 9 - use DoItAgain
+ */
+
+}
+
+@
+\subsection{fix\_env}
+insert SPADSERVER and SPADNUM variables into the environemnt
+<<sman.fixenv>>=
+static void
+fix_env(char **envp, int spadnum)
+{
+ int len, i;
+ char *sn;
+ for(len = 0; envp[len] != NULL; len++);
+ new_envp = (char **) malloc((len + 3) * sizeof(char *));
+ new_envp[0] = "SPADSERVER=TRUE";
+ sn = (char *) malloc(20 * sizeof(char));
+ sprintf(sn, "SPADNUM=%d", spadnum);
+ new_envp[1] = sn;
+ for(i=0; i<=len; i++)
+ new_envp[i+2] = envp[i];
+}
+
+@
+\subsection{init\_term\_io}
+<<sman.inittermio>>=
+static void
+init_term_io(void)
+{
+ if(!isatty(0)) return;
+ if( tcgetattr(0, &oldbuf) == -1) {
+ perror("getting termios");
+ return ; /* exit(-1); */
+ }
+ if( tcgetattr(0, &childbuf) == -1) {
+ perror("getting termios");
+ return ; /* exit(-1); */
+ }
+ _INTR = oldbuf.c_cc[VINTR];
+ _QUIT = oldbuf.c_cc[VQUIT];
+ _ERASE = oldbuf.c_cc[VERASE];
+ _KILL = oldbuf.c_cc[VKILL];
+ _EOF = oldbuf.c_cc[VEOF];
+ _EOL = oldbuf.c_cc[VEOL];
+}
+
+@
+\subsection{strPrefix}
+<<sman.strPrefix>>=
+static char *
+strPrefix(char *prefix,char * s)
+{
+ while (*prefix != '\0' && *prefix == *s) {
+ prefix++;
+ s++;
+ }
+ if (*prefix == '\0') return s;
+ return NULL;
+}
+
+@
+\subsection{check\_spad\_proc}
+<<sman.checkspadproc>>=
+static void
+check_spad_proc(char *file, char *prefix)
+{
+ char *num;
+ int pid;
+ if ((num = strPrefix(prefix, file))) {
+ pid = atoi(num);
+ if (pid > 2) {
+ kill(pid, 0);
+ if (kill(pid, 0) == -1 && errno == ESRCH) {
+ unlink(file);
+ }
+ }
+ }
+}
+
+@
+\subsection{clean\_up\_old\_sockets}
+<<sman.cleanupoldsockets>>=
+static void
+clean_up_old_sockets(void)
+{
+ char com[512], tmp_file[128];
+ FILE *file;
+ int len;
+ sprintf(tmp_file, "/tmp/socks.%d", server_num);
+ sprintf(com, "ls /tmp/.d* /tmp/.s* /tmp/.i* /tmp/.h* 2> %s > %s",
+ tmp_file, tmp_file);
+ system(com);
+ file = fopen(tmp_file, "r");
+ if (file == NULL) {
+ fprintf(stderr, "Can't open socket listing file\n");
+ return;
+ }
+ while(fgets(com, 512, file) != NULL) {
+ len = strlen(com);
+ if (len) com[len-1] = '\0';
+ else break;
+ check_spad_proc(com, "/tmp/.d");
+ check_spad_proc(com, "/tmp/.s");
+ check_spad_proc(com, "/tmp/.i");
+ check_spad_proc(com, "/tmp/.h");
+ }
+ fclose(file);
+ unlink(tmp_file);
+}
+
+@
+\subsection{fork\_you}
+<<sman.forkyou>>=
+static SpadProcess *
+fork_you(int death_action)
+{
+ /* fork a new process, giving it a default death action */
+ /* return NULL in child, SpadProcess in parent */
+ int child_pid = fork();
+ SpadProcess *proc;
+ if (!child_pid) return NULL;
+ proc = (SpadProcess *) malloc(sizeof(SpadProcess));
+ proc->proc_id = child_pid;
+ proc->death_action = death_action;
+ proc->command = NULL;
+ proc->next = spad_process_list;
+ spad_process_list = proc;
+ return proc;
+}
+
+@
+\subsection{exec\_command\_env}
+Note that the next-to-last argument of {\tt execle} must be an
+explicit NULL pointer. The previous naked 0 value was not correct.
+<<sman.execcommandenv>>=
+static void
+exec_command_env(char *command,char ** env)
+{
+ char new_command[512];
+ sprintf(new_command, "exec %s", command);
+ execle("/bin/sh","/bin/sh", "-c", new_command, (char *)0, env);
+}
+
+@
+\subsection{spawn\_of\_hell}
+<<sman.spawnofhell>>=
+static SpadProcess *
+spawn_of_hell(char *command, int death_action)
+{
+ SpadProcess *proc = fork_you(death_action);
+ if (proc != NULL) {
+ proc->command = command;
+ return proc;
+ }
+ exec_command_env(command, new_envp);
+ return NULL;
+}
+
+@
+\subsection{start\_the\_spadclient}
+run a AXIOM client in the main process
+<<sman.startthespadclient>>=
+static void
+start_the_spadclient(void)
+{
+ char command[256];
+ if (start_clef)
+#ifdef RIOSplatform
+ sprintf(command,
+ "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
+ ClefProgram, SpadClientProgram);
+#else
+ sprintf(command,
+ "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
+ ClefProgram, SpadClientProgram);
+#endif
+ else
+#ifdef RIOSplatform
+ sprintf(command,
+ "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s",
+ SpadClientProgram);
+#else
+ sprintf(command,
+ "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s",
+ SpadClientProgram);
+#endif
+ if (tpd == 1)
+ fprintf(stderr,"sman:start_the_spadclient: %s\n",command);
+ spawn_of_hell(command, NadaDelShitsky);
+}
+
+@
+\subsection{start\_the\_local\_spadclient}
+<<sman.startthelocalspadclient>>=
+static void
+start_the_local_spadclient(void)
+{
+ char command[256];
+ if (start_clef)
+ sprintf(command, "%s %s", ClefProgram, SpadClientProgram);
+ else
+ sprintf(command, "%s", SpadClientProgram);
+ if (tpd == 1)
+ fprintf(stderr,"sman:start_the_local_spadclient: %s\n",command);
+ spawn_of_hell(command, NadaDelShitsky);
+}
+
+@
+\subsection{start\_the\_nagman}
+<<sman.startthenagman>>=
+static void
+start_the_nagman(void)
+{
+#if defined(HP9platform)
+ spawn_of_hell(NagManagerProgram,DoItAgain);
+#else
+ spawn_of_hell(NagManagerProgram,NadaDelShitsky );
+#endif
+}
+
+@
+\subsection{start\_the\_session\_manager}
+<<sman.startthesessionmanager>>=
+static void
+start_the_session_manager(void)
+{
+ spawn_of_hell(SessionManagerProgram, Die);
+}
+
+@
+\subsection{start\_the\_hypertex}
+<<sman.startthehypertex>>=
+static void
+start_the_hypertex(void)
+{
+ char prog[512];
+
+ if (PasteFile){
+ sprintf(prog, "%s -k -ip %s", HypertexProgram, PasteFile);
+ spawn_of_hell(prog, NadaDelShitsky);
+ }
+ else if (MakeRecordFile){
+ sprintf(prog, "%s -k -rm %s", HypertexProgram,MakeRecordFile );
+ spawn_of_hell(prog, NadaDelShitsky);
+ }
+ else if (VerifyRecordFile){
+ sprintf(prog, "%s -k -rv %s", HypertexProgram, VerifyRecordFile);
+ spawn_of_hell(prog, NadaDelShitsky);
+ }
+ else spawn_of_hell(HypertexProgram, NadaDelShitsky);
+}
+
+@
+\subsection{start\_the\_graphics}
+<<sman.startthegraphics>>=
+static void
+start_the_graphics(void)
+{
+ spawn_of_hell(GraphicsProgram, DoItAgain);
+}
+
+@
+\subsection{fork\_Axiom}
+<<sman.forkAxiom>>=
+/* Start the AXIOM session in a separate process, */
+/* using a pseudo-terminal to catch all input and output */
+static void
+fork_Axiom(void)
+{
+ char augmented_ws_path[256]; /* will append directory path */
+ char *tmp_pointer;
+ SpadProcess *proc;
+
+ proc = fork_you(Die);
+ child_pid = (proc == NULL ? 0 : proc->proc_id);
+ switch(child_pid) {
+ case -1 :
+ fprintf(stderr, "Can't create a new process \n");
+ exit(0);
+ case 0:
+ /* Dissasociate from my parents group so all my child processes */
+ /* look at my terminal as the controlling terminal for the */
+ /* group */
+
+ if(setsid() < 0) {
+ perror("Dissassociating from parents group");
+ exit(-1);
+ }
+
+ close(ptsNum);
+ /* Now reopen the server side, so that pg, su, etc. work properly */
+
+ if ((ptsNum = open(ptsPath, O_RDWR)) < 0 ) {
+ perror("fork_Axiom: Failed to reopen server");
+ exit(-1);
+ }
+#if defined(SUN4OS5platform) || defined(HP10platform)
+ ioctl(ptsNum,I_PUSH,"ptem");
+ ioctl(ptsNum,I_PUSH,"ldterm");
+#endif
+
+ /* since I am the child, I can close ptc, and dup pts for all its */
+ /* standard descriptors */
+
+ if( (dup2(ptsNum, 0) == -1) ||
+ (dup2(ptsNum, 1) == -1) ||
+ (dup2(ptsNum, 2) == -1) ) {
+ perror("trying to dupe the child");
+ exit(-1);
+ }
+ close(ptcNum);
+ close(ptsNum);
+
+
+ /* I also have to turn off echoing, since I am echoing all the */
+ /* input myself */
+
+ childbuf.c_lflag &= ~ECHO;
+ if( tcsetattr(0, TCSAFLUSH, &childbuf) == -1) {
+ perror("setting the term buffer");
+ exit(-1);
+ }
+ strcpy(augmented_ws_path,ws_path); /* write the name */
+ strcat(augmented_ws_path," "); /* space */
+ strcat(augmented_ws_path,ws_path); /* name again */
+ tmp_pointer = (char *)
+ strrchr(augmented_ws_path,'/'); /*pointer to last / */
+ *(++tmp_pointer) = '\0';
+ exec_command_env(augmented_ws_path, new_envp);
+
+ /* fprintf(stderr, "Cannot execute the %s system.\n", ws_path); */
+
+ exit(0);
+ }
+}
+
+@
+\subsection{start\_the\_Axiom}
+<<sman.starttheAxiom>>=
+static void
+start_the_Axiom(char **envp)
+{
+ server_num = make_server_number();
+ clean_up_old_sockets();
+ if (server_num == -1) {
+ fprintf(stderr, "could not get an AXIOM server number\n");
+ exit(-1);
+ }
+ if (ptyopen(&ptcNum, &ptsNum, ptcPath, ptsPath) == -1) {
+ perror("start_the_Axiom: ptyopen failed");
+ exit(-1);
+ }
+ fix_env(envp, server_num);
+ fork_Axiom();
+ close(ptsNum);
+}
+
+@
+\subsection{clean\_up\_sockets}
+<<sman.cleanupsockets>>=
+static void
+clean_up_sockets(void)
+{
+ char name[256];
+ sprintf(name, "%s%d", SpadServer, server_num);
+ unlink(name);
+ sprintf(name, "%s%d", SessionServer, server_num);
+ unlink(name);
+ sprintf(name, "%s%d", SessionIOName, server_num);
+ unlink(name);
+ sprintf(name, "%s%d", MenuServerName, server_num);
+ unlink(name);
+}
+
+@
+\subsection{read\_from\_spad\_io}
+<<sman.readfromspadio>>=
+static void
+read_from_spad_io(int ptcNum)
+{
+ int ret_code = 0, i=0;
+ static int mes_len =0;
+ ret_code = read(ptcNum, big_bad_buf, BufSize);
+ if (ret_code == -1) {
+ clean_up_sockets();
+ exit(-1);
+ }
+ if (session_io == NULL) {
+ if (ret_code < mes_len)
+ mes_len -= ret_code;
+ else {
+ if (mes_len > 0) {
+ i = mes_len;
+ mes_len = 0;
+ }
+ else
+ i = 0;
+ ret_code = write(1, big_bad_buf+i, ret_code-i);
+ }
+ }
+ else
+ ret_code = swrite(session_io, big_bad_buf, ret_code,
+ "writing to session man");
+ if (ret_code == -1) {
+ perror("writing output to session manager");
+ clean_up_sockets();
+ exit(-1);
+ }
+}
+
+@
+\subsection{read\_from\_manager}
+<<sman.readfrommanager>>=
+static void
+read_from_manager(int ptcNum)
+{
+ int ret_code;
+ ret_code = sread(session_io, big_bad_buf, BufSize, "reading session io");
+ if (ret_code == -1) {
+ return;
+ }
+ ret_code = write(ptcNum, big_bad_buf, ret_code);
+ if (ret_code == -1) {
+ return;
+ }
+}
+
+@
+\subsection{manage\_spad\_io}
+<<sman.managespadio>>=
+static void
+manage_spad_io(int ptcNum)
+{
+ int ret_code, i, p;
+ fd_set rd;
+ while (1) {
+ rd = socket_mask;
+ FD_SET(ptcNum, &rd);
+ if (session_io != NULL)
+ FD_SET(session_io->socket, &rd);
+ ret_code = sselect(FD_SETSIZE, &rd, 0, 0, NULL);
+ if (ret_code == -1) {
+ perror("Session manager select");
+ clean_up_sockets();
+ exit(-1);
+ }
+ if (FD_ISSET(ptcNum, &rd)) {
+ read_from_spad_io(ptcNum);
+ }
+ for(i=0; i<2; i++) {
+ if (server[i].socket > 0 && FD_ISSET(server[i].socket, &rd)) {
+ p = accept_connection(server+i);
+ switch(p) {
+ case SessionIO:
+ session_io = purpose_table[SessionIO];
+ /* printf("connected session manager\n\r");*/
+ printf("\n");
+ break;
+ default:
+ printf("sman: Unkown connection request type: %d\n", p);
+ break;
+ }
+ }
+ }
+ if (session_io != NULL && FD_ISSET(session_io->socket, &rd)) {
+ read_from_manager(ptcNum);
+ }
+ }
+}
+
+@
+\subsection{init\_spad\_process\_list}
+<<sman.initspadprocesslist>>=
+static void
+init_spad_process_list(void)
+{
+ spad_process_list = NULL;
+}
+
+@
+\subsection{print\_spad\_process\_list}
+<<sman.printspadprocesslist>>=
+#if 0
+static void
+print_spad_process_list()
+{
+ SpadProcess *proc;
+ for(proc = spad_process_list; proc != NULL; proc = proc->next)
+ fprintf(stderr, "proc_id = %d, death_action = %d\n", proc->proc_id,
+ proc->death_action);
+}
+#endif
+
+@
+\subsection{find\_child}
+<<sman.findchild>>=
+static SpadProcess *
+find_child(int proc_id)
+{
+ SpadProcess *proc;
+ for(proc = spad_process_list; proc != NULL; proc = proc->next)
+ if (proc->proc_id == proc_id) return proc;
+ return NULL;
+}
+
+@
+\subsection{kill\_all\_children}
+<<sman.killallchildren>>=
+static void
+kill_all_children(void)
+{
+ char name[256];
+ SpadProcess *proc;
+
+
+ for(proc = spad_process_list; proc != NULL; proc = proc->next) {
+ kill(proc->proc_id, SIGTERM);
+ }
+ sprintf(name, "/tmp/hyper%d.input",server_num);
+ unlink(name);
+
+}
+
+@
+\subsection{clean\_up\_terminal}
+<<sman.cleanupterminal>>=
+static void
+clean_up_terminal(void)
+{
+ tcsetattr(0, TCSAFLUSH, &oldbuf);
+}
+
+@
+\subsection{monitor\_children}
+<<sman.monitorchildren>>=
+static void
+monitor_children(void)
+{
+ int dead_baby, stat;
+ SpadProcess *proc;
+ while (1) {
+ stat = 0;
+ dead_baby = wait(&stat);
+ /* Check the value of dead_baby, since wait may have returned
+ a pid but subsequently we have received a signal. Yeuch! */
+ if (dead_baby == -1 && death_signal) {
+ kill_all_children();
+ clean_up_sockets();
+ clean_up_terminal();
+ sleep(2);
+ exit(0);
+ }
+ /* Check the value of dead_baby, since wait may have returned
+ a pid but subsequently we have received a signal. Yeuch! */
+ if(dead_baby == -1 && nagman_signal) {
+ nagman_signal=0;
+ spawn_of_hell(NagManagerProgram,NadaDelShitsky);
+ continue;
+ }
+
+ if (dead_baby == -1) {
+ fprintf(stderr, "sman: wait returned -1\n");
+ continue;
+ }
+ proc = find_child(dead_baby);
+ if (proc == NULL) {
+ /* fprintf(stderr, "sman: %d is not known to be a child process\n",
+ dead_baby);
+ */
+ continue;
+ }
+ switch(proc->death_action) {
+ case Die:
+ kill_all_children();
+ clean_up_sockets();
+ clean_up_terminal();
+ sleep(2);
+ exit(0);
+ case NadaDelShitsky:
+ break;
+ case DoItAgain:
+ spawn_of_hell(proc->command, DoItAgain);
+ break;
+ }
+ }
+}
+
+@
+\subsection{main sman}
+The main procedure should return an [[int]]. We change the return value
+here and in [[src/include/sman.h1]].
+<<sman.result>>=
+ return(0);
+@
+<<sman.main>>=
+int
+main(int argc, char *argv[],char *envp[])
+{
+ if (tpd == 1) fprintf(stderr,"sman:main entered\n");
+ bsdSignal(SIGINT, SIG_IGN,RestartSystemCalls);
+ process_options(argc, argv);
+
+ init_term_io();
+ init_spad_process_list();
+ start_the_Axiom(envp);
+ if (open_server(SessionIOName) == -2) {
+ fprintf(stderr, "Fatal error opening I/O socket\n");
+ clean_up_sockets();
+ exit(-1);
+ }
+ start_the_session_manager();
+ if (start_spadclient) start_the_spadclient();
+ if (start_local_spadclient) start_the_local_spadclient();
+ if (start_nagman) start_the_nagman();
+ if (start_ht) start_the_hypertex();
+ if (start_graphics) start_the_graphics();
+ sleep(1);
+
+ if (fork_you(Die) != NULL) {
+ sman_catch_signals();
+ monitor_children();
+ exit(0);
+ }
+ manage_spad_io(ptcNum);
+ if (tpd == 1) fprintf(stderr,"sman:main exit\n");
+<<sman.result>>
+}
+
+@
+\subsection{sman}
+<<sman>>=
+#define _SMAN_C
+
+<<sman.includes>>
+<<sman.variables>>
+<<sman.processarguments>>
+<<sman.shouldIclef>>
+<<sman.inX>>
+<<sman.setupdefaults>>
+<<sman.processoptions>>
+<<sman.deathhandler>>
+<<sman.nagmanhandler>>
+<<sman.smancatchsignals>>
+<<sman.fixenv>>
+<<sman.inittermio>>
+<<sman.strPrefix>>
+<<sman.checkspadproc>>
+<<sman.cleanupoldsockets>>
+<<sman.forkyou>>
+<<sman.execcommandenv>>
+<<sman.spawnofhell>>
+<<sman.startthespadclient>>
+<<sman.startthelocalspadclient>>
+<<sman.startthenagman>>
+<<sman.startthesessionmanager>>
+<<sman.startthehypertex>>
+<<sman.startthegraphics>>
+<<sman.forkAxiom>>
+<<sman.starttheAxiom>>
+<<sman.cleanupsockets>>
+<<sman.readfromspadio>>
+<<sman.readfrommanager>>
+<<sman.managespadio>>
+<<sman.initspadprocesslist>>
+<<sman.printspadprocesslist>>
+<<sman.findchild>>
+<<sman.killallchildren>>
+<<sman.cleanupterminal>>
+<<sman.monitorchildren>>
+<<sman.main>>
+
@
\chapter{Support Routines}
\section{Command Completion}
@@ -1565,1037 +2994,6 @@ main(void)
}
@
-\chapter{The {\tt sman} program}
-\section{sman.h}
-The spad\_proc structure holds information about the process id
-of a child process, what to do when it dies, and the shell command
-line necessary to restart the process. There is a linked list of
-these structures which maintains the process list for axiom.
-<<sman.h>>=
-/* Process control definitions. Used by fork_you and spawn_of_hell */
-
-/* When a process dies it kills off everything else */
-#define Die 1
-/* When a process dies, do nothing */
-#define NadaDelShitsky 2
-/* When a process dies start it up again */
-#define DoItAgain 3
-
-typedef struct spad_proc {
- int proc_id; /* process id of child */
- int death_action; /* one of the above constants */
- char *command; /* sh command line to restart the process */
- struct spad_proc *next;
-} SpadProcess;
-
-@
-\section{sman}
-\subsection{includes}
-<<sman.includes>>=
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <pwd.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#if defined(SUN4OS5platform) || defined(HP10platform)
-#include <sys/stropts.h>
-#endif
-
-#include "com.h"
-#include "bsdsignal.h"
-#include "sman.h"
-
-#include "bsdsignal.h1"
-#include "sockio-c.h1"
-#include "openpty.h1"
-#include "sman.h1"
-
-@
-\subsection{variables}
-<<sman.variables>>=
-char *ws_path; /* location of the AXIOM executable */
-int start_clef; /* start clef under spad */
-int start_graphics; /* start the viewman */
-int start_nagman; /* start the nagman */
-int start_ht; /* start hypertex */
-int start_spadclient; /* Start the client spad buffer */
-int start_local_spadclient; /* Start the client spad buffer */
-int use_X; /* Use the X windows environment */
-int server_num; /* AXIOM server number */
-@
-We add a debug flag so we can print information about what [[sman]]
-is trying to do. This change is pervasive as it touches nearly every
-routine.
-<<sman.variables>>=
-int tpd=0; /* to-print-debug information */
-
-/************************************************/
-/* definitions of programs which sman can start */
-/************************************************/
-
-<<the viewman command line>>
-<<the nagman command line>>
-<<the hypertex command line>>
-<<the clef command line>>
-<<the session manager command line>>
-<<the spadclient command line>>
-char *PasteFile = NULL;
-char *MakeRecordFile = NULL;
-char *VerifyRecordFile = NULL;
-
-SpadProcess *spad_process_list = NULL;
-/***************************/
-/* sman defaults file name */
-/***************************/
-
-#define SpadDefaultFile "spadprof.input"
-
-char ClefCommandLine[256];
-
-#define BufSize 4096 /* size of communication buffer */
-char big_bad_buf[BufSize]; /* big I/O buffer */
-
-Sock *session_io = NULL; /* socket connecting to session manager */
-
-/***********************************************************/
-/* Some characters used and externally defined in edible.h */
-/***********************************************************/
-
-unsigned char _INTR, _QUIT, _ERASE, _KILL, _EOF, _EOL, _RES1, _RES2;
-
-/*************************************/
-/* Stuff for opening pseudo-terminal */
-/*************************************/
-
-int ptsNum, ptcNum;
-char ptsPath[20], ptcPath[20];
-
-char **new_envp; /* new environment for AXIOM */
-int child_pid; /* child's process id */
-struct termios oldbuf; /* the original settings */
-struct termios childbuf; /* terminal structure for user i/o */
-
-int nagman_signal=0;
-int death_signal = 0;
-
-@
-\subsection{process\_arguments}
-<<sman.processarguments>>=
-static void
-process_arguments(int argc,char ** argv)
-{
- int arg;
- if (tpd == 1) fprintf(stderr,"sman:process_arguments entered\n");
- for (arg = 1; arg < argc; arg++) {
- if (strcmp(argv[arg], "-debug") == 0)
- tpd = 1;
- else if (strcmp(argv[arg], "-noclef") == 0)
- start_clef = 0;
- else if (strcmp(argv[arg], "-clef") == 0)
- start_clef = 1;
- else if (strcmp(argv[arg], "-gr") == 0)
- start_graphics = 1;
- else if (strcmp(argv[arg], "-nogr") == 0)
- start_graphics = 0;
- else if (strcmp(argv[arg], "-nag") == 0)
- start_nagman = 1;
- else if (strcmp(argv[arg], "-nonag") == 0)
- start_nagman = 0;
- else if (strcmp(argv[arg], "-ht") == 0)
- start_ht = 1;
- else if (strcmp(argv[arg], "-noht") == 0)
- start_ht = 0;
- else if (strcmp(argv[arg], "-iw") == 0)
- start_spadclient = 1;
- else if (strcmp(argv[arg], "-ihere") == 0)
- start_local_spadclient = 1;
- else if (strcmp(argv[arg], "-noihere") == 0)
- start_local_spadclient = 0;
- else if (strcmp(argv[arg], "-noiw") == 0)
- start_spadclient = 0;
- else if (strcmp(argv[arg], "-ws") == 0)
- ws_path = argv[++arg];
- else if (strcmp(argv[arg], "-comp") == 0)
- ws_path = "$AXIOM/etc/images/comp";
- else if (strcmp(argv[arg], "-nox") == 0)
- {
- use_X = 0;
- start_local_spadclient = 1;
- start_spadclient = 0;
- start_ht = 0;
- start_graphics = 0;
- }
- else if (strcmp(argv[arg], "-grprog") == 0)
- GraphicsProgram = argv[++arg];
- else if (strcmp(argv[arg], "-nagprog") == 0)
- NagManagerProgram = argv[++arg];
- else if (strcmp(argv[arg], "-htprog") == 0)
- HypertexProgram = argv[++arg];
- else if (strcmp(argv[arg], "-clefprog") == 0) {
- strcpy(ClefCommandLine,argv[++arg]);
- ClefProgram =
- strcat(ClefCommandLine, " -f $AXIOM/lib/command.list -e ");
- }
- else if (strcmp(argv[arg], "-sessionprog") == 0)
- SessionManagerProgram = argv[++arg];
- else if (strcmp(argv[arg], "-clientprog") == 0)
- SpadClientProgram = argv[++arg];
- else if (strcmp(argv[arg], "-rm") == 0)
- MakeRecordFile = argv[++arg];
- else if (strcmp(argv[arg], "-rv") == 0)
- VerifyRecordFile = argv[++arg];
- else if (strcmp(argv[arg], "-paste") == 0)
- PasteFile = argv[++arg];
- else {
- fprintf(stderr, "Usage: sman <-clef|-noclef> <-gr|-nogr> <-ht|-noht>");
- fprintf(stderr, " <-iw|-noiw> <-nag|-nonag> <-nox> <-comp>");
- fprintf(stderr, " <-ws spad_workspace> <-grprog path> <-htprog path>");
- fprintf(stderr, " <-clefprog path> <-sessionprog path> <-nagprog path>");
- fprintf(stderr, " <-clientprog path>\n");
- exit(-1);
- }
- }
- if (tpd == 1)
- { fprintf(stderr," sman ");
- if (start_clef == 0)
- fprintf(stderr,"-noclef ");
- else
- fprintf(stderr,"-clef ");
- if (start_graphics == 0)
- fprintf(stderr,"-nogr ");
- else
- fprintf(stderr,"-gr ");
- if (start_nagman == 0)
- fprintf(stderr,"-nonag ");
- else
- fprintf(stderr,"-nag ");
- if (start_ht == 0)
- fprintf(stderr,"-noht ");
- else
- fprintf(stderr,"-ht ");
- if (start_spadclient == 0)
- fprintf(stderr,"-noiw ");
- else
- fprintf(stderr,"-iw ");
- if (start_local_spadclient == 0)
- fprintf(stderr,"-noihere ");
- else
- fprintf(stderr,"-ihere ");
- if (start_local_spadclient == 0)
- fprintf(stderr,"-noihere ");
- else
- fprintf(stderr,"-ihere ");
- if (use_X == 0)
- fprintf(stderr,"-nox ");
- fprintf(stderr,"-ws ");
- fprintf(stderr,"'%s' ",ws_path);
- fprintf(stderr,"-grprog ");
- fprintf(stderr,"'%s' ",GraphicsProgram);
- fprintf(stderr,"-nagprog ");
- fprintf(stderr,"'%s' ",NagManagerProgram);
- fprintf(stderr,"-htprog ");
- fprintf(stderr,"'%s' ",HypertexProgram);
- fprintf(stderr,"-clefprog ");
- fprintf(stderr,"'%s' ",ClefCommandLine);
- fprintf(stderr,"-sessionprog ");
- fprintf(stderr,"'%s' ",SessionManagerProgram);
- fprintf(stderr,"-clientprog ");
- fprintf(stderr,"'%s' ",SpadClientProgram);
- fprintf(stderr,"-rm ");
- fprintf(stderr,"'%s' ",MakeRecordFile);
- fprintf(stderr,"-rv ");
- fprintf(stderr,"'%s' ",VerifyRecordFile);
- fprintf(stderr,"-paste ");
- fprintf(stderr,"'%s' ",PasteFile);
- fprintf(stderr,"\n");
- }
- if (tpd == 1) fprintf(stderr,"sman:process_arguments exit\n");
-}
-
-@
-\subsection{should\_I\_clef}
-<<sman.shouldIclef>>=
-static int
-should_I_clef(void)
-{
- return(1);
-}
-
-@
-\subsection{in\_X}
-<<sman.inX>>=
-static int
-in_X(void)
-{
- if (getenv("DISPLAY")) return 1;
- return 0;
-}
-
-@
-\subsection{set\_up\_defaults}
-These are the default values for sman. A '1' value means that
-sman will try to start the given process, a '0' value means not
-starting the process.
-
-We do not have replacement code for the [[nagman]] process nor
-do we have a copy of the [[nag fortran library]] to test the process.
-Until this changes we set [[start_nagman = 0]] in order to disable
-starting this process by default.
-<<sman.setupdefaults>>=
-static void
-set_up_defaults(void)
-{
- if (tpd == 1) fprintf(stderr,"sman:set_up_defaults entered\n");
- start_clef = should_I_clef();
- start_graphics = 1;
- start_nagman = 0;
- start_ht = 1;
- start_spadclient = 0;
- start_local_spadclient = 1;
- use_X = isatty(0) && in_X();
- ws_path = "$AXIOM/bin/AXIOMsys";
- if (tpd == 1) fprintf(stderr,"sman:set_up_defaults exit\n");
-}
-
-@
-\subsection{process\_options}
-<<sman.processoptions>>=
-static void
-process_options(int argc, char **argv)
-{
- if (tpd == 1) fprintf(stderr,"sman:process_options entered\n");
- set_up_defaults();
- process_arguments(argc, argv);
- if (tpd == 1) fprintf(stderr,"sman:process_options exit\n");
-}
-
-@
-\subsection{death\_handler}
-<<sman.deathhandler>>=
-static void
-death_handler(int sig)
-{
- death_signal = 1;
-}
-
-@
-\subsection{nagman\_handler}
-<<sman.nagmanhandler>>=
-static void
-nagman_handler(int sig)
-{
- nagman_signal=1;
-}
-
-@
-\subsection{sman\_catch\_signals}
-<<sman.smancatchsignals>>=
-static void
-sman_catch_signals(void)
-{
-
- /* Set up the signal handlers for sman */
- bsdSignal(SIGINT, SIG_IGN,RestartSystemCalls);
- bsdSignal(SIGTERM, death_handler,RestartSystemCalls);
- bsdSignal(SIGQUIT, death_handler,RestartSystemCalls);
- bsdSignal(SIGHUP, death_handler,RestartSystemCalls);
- bsdSignal(SIGILL, death_handler,RestartSystemCalls);
- bsdSignal(SIGTRAP, death_handler,RestartSystemCalls);
- bsdSignal(SIGIOT, death_handler,RestartSystemCalls);
- bsdSignal(SIGBUS, death_handler,RestartSystemCalls);
- bsdSignal(SIGSEGV, death_handler,RestartSystemCalls);
- /* don't restart wait call on SIGUSR1 */
- bsdSignal(SIGUSR1, nagman_handler,DontRestartSystemCalls);
- /* ONLY nagman should send this.
- If an error (such as C-c) interrupts a NAGLINK call, nagman
- gets a signal to clean up. We need to start another nagman
- almost immediately to process the next NAGLINK request.
- Since nagman takes a while to clean up, we treat it specially.
- nagman should send a signal (USR1) to sman.
- sman should respond by spawning a new nagman.
-
- so nagman is NOT a DoItAgain but a NadaDelShitsky.
-
- The USR1 mechanism does not work for HPUX 9 - use DoItAgain
- */
-
-}
-
-@
-\subsection{fix\_env}
-insert SPADSERVER and SPADNUM variables into the environemnt
-<<sman.fixenv>>=
-static void
-fix_env(char **envp, int spadnum)
-{
- int len, i;
- char *sn;
- for(len = 0; envp[len] != NULL; len++);
- new_envp = (char **) malloc((len + 3) * sizeof(char *));
- new_envp[0] = "SPADSERVER=TRUE";
- sn = (char *) malloc(20 * sizeof(char));
- sprintf(sn, "SPADNUM=%d", spadnum);
- new_envp[1] = sn;
- for(i=0; i<=len; i++)
- new_envp[i+2] = envp[i];
-}
-
-@
-\subsection{init\_term\_io}
-<<sman.inittermio>>=
-static void
-init_term_io(void)
-{
- if(!isatty(0)) return;
- if( tcgetattr(0, &oldbuf) == -1) {
- perror("getting termios");
- return ; /* exit(-1); */
- }
- if( tcgetattr(0, &childbuf) == -1) {
- perror("getting termios");
- return ; /* exit(-1); */
- }
- _INTR = oldbuf.c_cc[VINTR];
- _QUIT = oldbuf.c_cc[VQUIT];
- _ERASE = oldbuf.c_cc[VERASE];
- _KILL = oldbuf.c_cc[VKILL];
- _EOF = oldbuf.c_cc[VEOF];
- _EOL = oldbuf.c_cc[VEOL];
-}
-
-@
-\subsection{strPrefix}
-<<sman.strPrefix>>=
-static char *
-strPrefix(char *prefix,char * s)
-{
- while (*prefix != '\0' && *prefix == *s) {
- prefix++;
- s++;
- }
- if (*prefix == '\0') return s;
- return NULL;
-}
-
-@
-\subsection{check\_spad\_proc}
-<<sman.checkspadproc>>=
-static void
-check_spad_proc(char *file, char *prefix)
-{
- char *num;
- int pid;
- if ((num = strPrefix(prefix, file))) {
- pid = atoi(num);
- if (pid > 2) {
- kill(pid, 0);
- if (kill(pid, 0) == -1 && errno == ESRCH) {
- unlink(file);
- }
- }
- }
-}
-
-@
-\subsection{clean\_up\_old\_sockets}
-<<sman.cleanupoldsockets>>=
-static void
-clean_up_old_sockets(void)
-{
- char com[512], tmp_file[128];
- FILE *file;
- int len;
- sprintf(tmp_file, "/tmp/socks.%d", server_num);
- sprintf(com, "ls /tmp/.d* /tmp/.s* /tmp/.i* /tmp/.h* 2> %s > %s",
- tmp_file, tmp_file);
- system(com);
- file = fopen(tmp_file, "r");
- if (file == NULL) {
- fprintf(stderr, "Can't open socket listing file\n");
- return;
- }
- while(fgets(com, 512, file) != NULL) {
- len = strlen(com);
- if (len) com[len-1] = '\0';
- else break;
- check_spad_proc(com, "/tmp/.d");
- check_spad_proc(com, "/tmp/.s");
- check_spad_proc(com, "/tmp/.i");
- check_spad_proc(com, "/tmp/.h");
- }
- fclose(file);
- unlink(tmp_file);
-}
-
-@
-\subsection{fork\_you}
-<<sman.forkyou>>=
-static SpadProcess *
-fork_you(int death_action)
-{
- /* fork a new process, giving it a default death action */
- /* return NULL in child, SpadProcess in parent */
- int child_pid = fork();
- SpadProcess *proc;
- if (!child_pid) return NULL;
- proc = (SpadProcess *) malloc(sizeof(SpadProcess));
- proc->proc_id = child_pid;
- proc->death_action = death_action;
- proc->command = NULL;
- proc->next = spad_process_list;
- spad_process_list = proc;
- return proc;
-}
-
-@
-\subsection{exec\_command\_env}
-Note that the next-to-last argument of {\tt execle} must be an
-explicit NULL pointer. The previous naked 0 value was not correct.
-<<sman.execcommandenv>>=
-static void
-exec_command_env(char *command,char ** env)
-{
- char new_command[512];
- sprintf(new_command, "exec %s", command);
- execle("/bin/sh","/bin/sh", "-c", new_command, (char *)0, env);
-}
-
-@
-\subsection{spawn\_of\_hell}
-<<sman.spawnofhell>>=
-static SpadProcess *
-spawn_of_hell(char *command, int death_action)
-{
- SpadProcess *proc = fork_you(death_action);
- if (proc != NULL) {
- proc->command = command;
- return proc;
- }
- exec_command_env(command, new_envp);
- return NULL;
-}
-
-@
-\subsection{start\_the\_spadclient}
-run a AXIOM client in the main process
-<<sman.startthespadclient>>=
-static void
-start_the_spadclient(void)
-{
- char command[256];
- if (start_clef)
-#ifdef RIOSplatform
- sprintf(command,
- "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
- ClefProgram, SpadClientProgram);
-#else
- sprintf(command,
- "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s %s",
- ClefProgram, SpadClientProgram);
-#endif
- else
-#ifdef RIOSplatform
- sprintf(command,
- "aixterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s",
- SpadClientProgram);
-#else
- sprintf(command,
- "xterm -sb -sl 500 -name axiomclient -n AXIOM -T AXIOM -e %s",
- SpadClientProgram);
-#endif
- if (tpd == 1)
- fprintf(stderr,"sman:start_the_spadclient: %s\n",command);
- spawn_of_hell(command, NadaDelShitsky);
-}
-
-@
-\subsection{start\_the\_local\_spadclient}
-<<sman.startthelocalspadclient>>=
-static void
-start_the_local_spadclient(void)
-{
- char command[256];
- if (start_clef)
- sprintf(command, "%s %s", ClefProgram, SpadClientProgram);
- else
- sprintf(command, "%s", SpadClientProgram);
- if (tpd == 1)
- fprintf(stderr,"sman:start_the_local_spadclient: %s\n",command);
- spawn_of_hell(command, NadaDelShitsky);
-}
-
-@
-\subsection{start\_the\_nagman}
-<<sman.startthenagman>>=
-static void
-start_the_nagman(void)
-{
-#if defined(HP9platform)
- spawn_of_hell(NagManagerProgram,DoItAgain);
-#else
- spawn_of_hell(NagManagerProgram,NadaDelShitsky );
-#endif
-}
-
-@
-\subsection{start\_the\_session\_manager}
-<<sman.startthesessionmanager>>=
-static void
-start_the_session_manager(void)
-{
- spawn_of_hell(SessionManagerProgram, Die);
-}
-
-@
-\subsection{start\_the\_hypertex}
-<<sman.startthehypertex>>=
-static void
-start_the_hypertex(void)
-{
- char prog[512];
-
- if (PasteFile){
- sprintf(prog, "%s -k -ip %s", HypertexProgram, PasteFile);
- spawn_of_hell(prog, NadaDelShitsky);
- }
- else if (MakeRecordFile){
- sprintf(prog, "%s -k -rm %s", HypertexProgram,MakeRecordFile );
- spawn_of_hell(prog, NadaDelShitsky);
- }
- else if (VerifyRecordFile){
- sprintf(prog, "%s -k -rv %s", HypertexProgram, VerifyRecordFile);
- spawn_of_hell(prog, NadaDelShitsky);
- }
- else spawn_of_hell(HypertexProgram, NadaDelShitsky);
-}
-
-@
-\subsection{start\_the\_graphics}
-<<sman.startthegraphics>>=
-static void
-start_the_graphics(void)
-{
- spawn_of_hell(GraphicsProgram, DoItAgain);
-}
-
-@
-\subsection{fork\_Axiom}
-<<sman.forkAxiom>>=
-/* Start the AXIOM session in a separate process, */
-/* using a pseudo-terminal to catch all input and output */
-static void
-fork_Axiom(void)
-{
- char augmented_ws_path[256]; /* will append directory path */
- char *tmp_pointer;
- SpadProcess *proc;
-
- proc = fork_you(Die);
- child_pid = (proc == NULL ? 0 : proc->proc_id);
- switch(child_pid) {
- case -1 :
- fprintf(stderr, "Can't create a new process \n");
- exit(0);
- case 0:
- /* Dissasociate from my parents group so all my child processes */
- /* look at my terminal as the controlling terminal for the */
- /* group */
-
- if(setsid() < 0) {
- perror("Dissassociating from parents group");
- exit(-1);
- }
-
- close(ptsNum);
- /* Now reopen the server side, so that pg, su, etc. work properly */
-
- if ((ptsNum = open(ptsPath, O_RDWR)) < 0 ) {
- perror("fork_Axiom: Failed to reopen server");
- exit(-1);
- }
-#if defined(SUN4OS5platform) || defined(HP10platform)
- ioctl(ptsNum,I_PUSH,"ptem");
- ioctl(ptsNum,I_PUSH,"ldterm");
-#endif
-
- /* since I am the child, I can close ptc, and dup pts for all its */
- /* standard descriptors */
-
- if( (dup2(ptsNum, 0) == -1) ||
- (dup2(ptsNum, 1) == -1) ||
- (dup2(ptsNum, 2) == -1) ) {
- perror("trying to dupe the child");
- exit(-1);
- }
- close(ptcNum);
- close(ptsNum);
-
-
- /* I also have to turn off echoing, since I am echoing all the */
- /* input myself */
-
- childbuf.c_lflag &= ~ECHO;
- if( tcsetattr(0, TCSAFLUSH, &childbuf) == -1) {
- perror("setting the term buffer");
- exit(-1);
- }
- strcpy(augmented_ws_path,ws_path); /* write the name */
- strcat(augmented_ws_path," "); /* space */
- strcat(augmented_ws_path,ws_path); /* name again */
- tmp_pointer = (char *)
- strrchr(augmented_ws_path,'/'); /*pointer to last / */
- *(++tmp_pointer) = '\0';
- exec_command_env(augmented_ws_path, new_envp);
-
- /* fprintf(stderr, "Cannot execute the %s system.\n", ws_path); */
-
- exit(0);
- }
-}
-
-@
-\subsection{start\_the\_Axiom}
-<<sman.starttheAxiom>>=
-static void
-start_the_Axiom(char **envp)
-{
- server_num = make_server_number();
- clean_up_old_sockets();
- if (server_num == -1) {
- fprintf(stderr, "could not get an AXIOM server number\n");
- exit(-1);
- }
- if (ptyopen(&ptcNum, &ptsNum, ptcPath, ptsPath) == -1) {
- perror("start_the_Axiom: ptyopen failed");
- exit(-1);
- }
- fix_env(envp, server_num);
- fork_Axiom();
- close(ptsNum);
-}
-
-@
-\subsection{clean\_up\_sockets}
-<<sman.cleanupsockets>>=
-static void
-clean_up_sockets(void)
-{
- char name[256];
- sprintf(name, "%s%d", SpadServer, server_num);
- unlink(name);
- sprintf(name, "%s%d", SessionServer, server_num);
- unlink(name);
- sprintf(name, "%s%d", SessionIOName, server_num);
- unlink(name);
- sprintf(name, "%s%d", MenuServerName, server_num);
- unlink(name);
-}
-
-@
-\subsection{read\_from\_spad\_io}
-<<sman.readfromspadio>>=
-static void
-read_from_spad_io(int ptcNum)
-{
- int ret_code = 0, i=0;
- static int mes_len =0;
- ret_code = read(ptcNum, big_bad_buf, BufSize);
- if (ret_code == -1) {
- clean_up_sockets();
- exit(-1);
- }
- if (session_io == NULL) {
- if (ret_code < mes_len)
- mes_len -= ret_code;
- else {
- if (mes_len > 0) {
- i = mes_len;
- mes_len = 0;
- }
- else
- i = 0;
- ret_code = write(1, big_bad_buf+i, ret_code-i);
- }
- }
- else
- ret_code = swrite(session_io, big_bad_buf, ret_code,
- "writing to session man");
- if (ret_code == -1) {
- perror("writing output to session manager");
- clean_up_sockets();
- exit(-1);
- }
-}
-
-@
-\subsection{read\_from\_manager}
-<<sman.readfrommanager>>=
-static void
-read_from_manager(int ptcNum)
-{
- int ret_code;
- ret_code = sread(session_io, big_bad_buf, BufSize, "reading session io");
- if (ret_code == -1) {
- return;
- }
- ret_code = write(ptcNum, big_bad_buf, ret_code);
- if (ret_code == -1) {
- return;
- }
-}
-
-@
-\subsection{manage\_spad\_io}
-<<sman.managespadio>>=
-static void
-manage_spad_io(int ptcNum)
-{
- int ret_code, i, p;
- fd_set rd;
- while (1) {
- rd = socket_mask;
- FD_SET(ptcNum, &rd);
- if (session_io != NULL)
- FD_SET(session_io->socket, &rd);
- ret_code = sselect(FD_SETSIZE, &rd, 0, 0, NULL);
- if (ret_code == -1) {
- perror("Session manager select");
- clean_up_sockets();
- exit(-1);
- }
- if (FD_ISSET(ptcNum, &rd)) {
- read_from_spad_io(ptcNum);
- }
- for(i=0; i<2; i++) {
- if (server[i].socket > 0 && FD_ISSET(server[i].socket, &rd)) {
- p = accept_connection(server+i);
- switch(p) {
- case SessionIO:
- session_io = purpose_table[SessionIO];
- /* printf("connected session manager\n\r");*/
- printf("\n");
- break;
- default:
- printf("sman: Unkown connection request type: %d\n", p);
- break;
- }
- }
- }
- if (session_io != NULL && FD_ISSET(session_io->socket, &rd)) {
- read_from_manager(ptcNum);
- }
- }
-}
-
-@
-\subsection{init\_spad\_process\_list}
-<<sman.initspadprocesslist>>=
-static void
-init_spad_process_list(void)
-{
- spad_process_list = NULL;
-}
-
-@
-\subsection{print\_spad\_process\_list}
-<<sman.printspadprocesslist>>=
-#if 0
-static void
-print_spad_process_list()
-{
- SpadProcess *proc;
- for(proc = spad_process_list; proc != NULL; proc = proc->next)
- fprintf(stderr, "proc_id = %d, death_action = %d\n", proc->proc_id,
- proc->death_action);
-}
-#endif
-
-@
-\subsection{find\_child}
-<<sman.findchild>>=
-static SpadProcess *
-find_child(int proc_id)
-{
- SpadProcess *proc;
- for(proc = spad_process_list; proc != NULL; proc = proc->next)
- if (proc->proc_id == proc_id) return proc;
- return NULL;
-}
-
-@
-\subsection{kill\_all\_children}
-<<sman.killallchildren>>=
-static void
-kill_all_children(void)
-{
- char name[256];
- SpadProcess *proc;
-
-
- for(proc = spad_process_list; proc != NULL; proc = proc->next) {
- kill(proc->proc_id, SIGTERM);
- }
- sprintf(name, "/tmp/hyper%d.input",server_num);
- unlink(name);
-
-}
-
-@
-\subsection{clean\_up\_terminal}
-<<sman.cleanupterminal>>=
-static void
-clean_up_terminal(void)
-{
- tcsetattr(0, TCSAFLUSH, &oldbuf);
-}
-
-@
-\subsection{monitor\_children}
-<<sman.monitorchildren>>=
-static void
-monitor_children(void)
-{
- int dead_baby, stat;
- SpadProcess *proc;
- while (1) {
- stat = 0;
- dead_baby = wait(&stat);
- /* Check the value of dead_baby, since wait may have returned
- a pid but subsequently we have received a signal. Yeuch! */
- if (dead_baby == -1 && death_signal) {
- kill_all_children();
- clean_up_sockets();
- clean_up_terminal();
- sleep(2);
- exit(0);
- }
- /* Check the value of dead_baby, since wait may have returned
- a pid but subsequently we have received a signal. Yeuch! */
- if(dead_baby == -1 && nagman_signal) {
- nagman_signal=0;
- spawn_of_hell(NagManagerProgram,NadaDelShitsky);
- continue;
- }
-
- if (dead_baby == -1) {
- fprintf(stderr, "sman: wait returned -1\n");
- continue;
- }
- proc = find_child(dead_baby);
- if (proc == NULL) {
- /* fprintf(stderr, "sman: %d is not known to be a child process\n",
- dead_baby);
- */
- continue;
- }
- switch(proc->death_action) {
- case Die:
- kill_all_children();
- clean_up_sockets();
- clean_up_terminal();
- sleep(2);
- exit(0);
- case NadaDelShitsky:
- break;
- case DoItAgain:
- spawn_of_hell(proc->command, DoItAgain);
- break;
- }
- }
-}
-
-@
-\subsection{main sman}
-The main procedure should return an [[int]]. We change the return value
-here and in [[src/include/sman.h1]].
-<<sman.result>>=
- return(0);
-@
-<<sman.main>>=
-int
-main(int argc, char *argv[],char *envp[])
-{
- if (tpd == 1) fprintf(stderr,"sman:main entered\n");
- bsdSignal(SIGINT, SIG_IGN,RestartSystemCalls);
- process_options(argc, argv);
-
- init_term_io();
- init_spad_process_list();
- start_the_Axiom(envp);
- if (open_server(SessionIOName) == -2) {
- fprintf(stderr, "Fatal error opening I/O socket\n");
- clean_up_sockets();
- exit(-1);
- }
- start_the_session_manager();
- if (start_spadclient) start_the_spadclient();
- if (start_local_spadclient) start_the_local_spadclient();
- if (start_nagman) start_the_nagman();
- if (start_ht) start_the_hypertex();
- if (start_graphics) start_the_graphics();
- sleep(1);
-
- if (fork_you(Die) != NULL) {
- sman_catch_signals();
- monitor_children();
- exit(0);
- }
- manage_spad_io(ptcNum);
- if (tpd == 1) fprintf(stderr,"sman:main exit\n");
-<<sman.result>>
-}
-
-@
-\subsection{sman}
-<<sman>>=
-#define _SMAN_C
-
-<<sman.includes>>
-<<sman.variables>>
-<<sman.processarguments>>
-<<sman.shouldIclef>>
-<<sman.inX>>
-<<sman.setupdefaults>>
-<<sman.processoptions>>
-<<sman.deathhandler>>
-<<sman.nagmanhandler>>
-<<sman.smancatchsignals>>
-<<sman.fixenv>>
-<<sman.inittermio>>
-<<sman.strPrefix>>
-<<sman.checkspadproc>>
-<<sman.cleanupoldsockets>>
-<<sman.forkyou>>
-<<sman.execcommandenv>>
-<<sman.spawnofhell>>
-<<sman.startthespadclient>>
-<<sman.startthelocalspadclient>>
-<<sman.startthenagman>>
-<<sman.startthesessionmanager>>
-<<sman.startthehypertex>>
-<<sman.startthegraphics>>
-<<sman.forkAxiom>>
-<<sman.starttheAxiom>>
-<<sman.cleanupsockets>>
-<<sman.readfromspadio>>
-<<sman.readfrommanager>>
-<<sman.managespadio>>
-<<sman.initspadprocesslist>>
-<<sman.printspadprocesslist>>
-<<sman.findchild>>
-<<sman.killallchildren>>
-<<sman.cleanupterminal>>
-<<sman.monitorchildren>>
-<<sman.main>>
-
-@
\chapter{The Command Completion List}
<<command.list>>=
-
@@ -6723,11 +7121,11 @@ XExponentialPackage
ZeroDimensionalSolvePackage
@
\begin{thebibliography}{99}
-\bibitem{1} Jenks, R.J. and Sutor, R.S.
-``Axiom -- The Scientific Computation System''
+\bibitem{1} Jenks, R.J. and Sutor, R.S. \\
+``Axiom -- The Scientific Computation System''\\
Springer-Verlag New York (1992)
ISBN 0-387-97855-0
-\bibitem{2} Knuth, Donald E., ``Literate Programming''
+\bibitem{2} Knuth, Donald E., ``Literate Programming''\\
Center for the Study of Language and Information
ISBN 0-937073-81-4
Stanford CA (1992)
@@ -6735,11 +7133,20 @@ Stanford CA (1992)
{\bf http://wiki.axiom-developer.org}
\bibitem{4} Watt, Stephen, ``Aldor'',\\
{\bf http://www.aldor.org}
-\bibitem{5} Lamport, Leslie, ``Latex -- A Document Preparation System'',
+\bibitem{5} Lamport, Leslie,\\
+``Latex -- A Document Preparation System'',
Addison-Wesley, New York ISBN 0-201-52983-1
-\bibitem{6} Ramsey, Norman ``Noweb -- A Simple, Extensible Tool for
-Literate Programming''\\
+\bibitem{6} Ramsey, Norman\\
+``Noweb -- A Simple, Extensible Tool for Literate Programming''\\
{\bf http://www.eecs.harvard.edu/ $\tilde{}$nr/noweb}
+\bibitem{7} Axiom Book Volume 7 -- Hyperdoc\\
+{\bf file://usr/local/axiom/src/hyper/bookvol7.pamphlet}
+\bibitem{8} Axiom Book Volume 8 -- Graphics\\
+{\bf file://usr/local/axiom/src/graph/bookvol8.pamphlet}
+\bibitem{9} AIX Version 3.2 and 4 Performance Tuning Guide\\
+{\bf
+http://www.rs6000.ibm.com/doc\_link/en\_US/\\
+{\hbox {\hskip 1.0cm}}a\_doc\_lib/aixbman/prftungd/toc.htm}
\end{thebibliography}
\printindex
\end{document}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Axiom-developer] 20070822.01.tpd.patch applied to silver,
daly <=