axiom-developer
[Top][All Lists]
Advanced

[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}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]