GUIDE to the SAM Distribution

which includes content also found in these tarballs:

   SAM.base
   SAM.tool

Updated 2023-09-14

Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012,
2014, 2015, 2018, 2020, 2021, 2023 Joseph Rosevear



# Joseph Rosevear 2003 I wrote this GUIDE and have since made many
# changes.

# Joseph Rosevear 230601 I made extensive changes in section 5, Running
# SAM.

# I moved file ENV-NOTES to junk and began the process of removing
# references to it from this GUIDE.

# I changed the title of this GUIDE consistent with a change in name. 
# SAM was known as "SAM Kernel and Application".  Now I simply call it
# SAM.

# I made changes to sections 1-4.

# I removed and/or rewrote all references to sam_distro.



1.  A short table of references in this distribution.

2.  What is this?

3.  Some terminology.

4.  Installing SAM.

5.  Running SAM.

6.  Using SAM.

6.1 The SAM prompt.

7.  About SAM menus.

8.  Special variables.

9.  There is a nuisance you may encounter.

10. SAM's temporary and scratch directories.

11. Shells used.

12. SAM.tool.

***


1.  Informative files in this distribution.

$sam_root
---------
CONTENTS
COPYING
GUIDE
README
TIPS

$sam_root is the root of the installation.

$sam_root/GUIDE is a symlink:

   GUIDE->$sam_root/main/about/doc/data/GUIDE

2.  What is this?  This is a distribution of SAM which includes content
also found in tarballs SAM.base and SAM.tool.  It was written by me,
Joseph Rosevear.  See file COPYING in this distribution for a statement
of the license agreement.


3.  Some terminology.  I distribute SAM as a tarball.  A "tarball" is a
directory tree compressed into a single file by use of tar.

I have in the past referred to SAM as "SAM Kernel and Application", "An
Application of SAM for GNU/Linux Slackware, or "SAM-GLS".  These are
all the same project, although it has changed over time in content,
structure and function.


4.  Installing SAM.

As I mentioned above, I distribute SAM as a tarball.  The SAM tarball
contains content also distrubuted separately in tarballs SAM.base and
SAM.tool.

   To install SAM, simply unpack the SAM tarball into a directory of
   your choosing.

At one point in the past I distributed SAM as traditional Slackware
package archives that end with ".tgz".  I have abandoned that method in
favor of simple tarballs.  There is very little compiled code in SAM,
and so little benefit comes from use of Slackware packages for it.  In
fact, this would perhaps be misleading.

Also in the past I distributed a large body of code.  The part of SAM
that I called the "kernel" was quite small, but I included also useful
tools and many examples of the use of SAM.  The result was hard for me
to manage well, and didn't do much to encourage people to try SAM.

My new approach is to distribute SAM both as a combination-tarball
(SAM.base plus SAM.tool) and as individual tarballs.  I will refer to
the combination-tarball as "SAM", and this is all I will distribute
initially.  The list of individual tarballs is in flux.  I hope to
provide many of them, as I have written much code that uses SAM, and I
would like to share it.

SAM.base will include the SAM kernel.  Whereas I previously provided
the kernel separately, I will no longer do this.  The kernel is small,
in a separate directory, and of no use by itself.  It made to sense to
distribute it separately.

SAM.base will also include other code that is not part of the kernel,
but is needed to make SAM run.

SAM now has a special directory, $sam_root/lib.  It is place for
installed SAM "libraries".  SAM comes with SAM.tool installed in
$sam_root/lib.

Something else that is new is that SAM now works well in a "dual" mode. 
The dual mode isn't required to run SAM.  SAM works fine in the normal
mode, and you should use it initially to get familiar with SAM.  The
dual mode, however, allows you to configure SAM without changing
anything in the installed distribution.

Instead, the user makes a directory which mirrors the root of the
installed distribution and adds a few symlinks to files in the
installed distribution.  "$sam_root" always refers to the installed
distribution.  I put my mirrored SAM root at /mnt/joe_root.  (This
means I put it somewhere then put a symbolic link to it called
"joe_root" at /mnt/joe_root.)  In this guide I'll call your mirrored
SAM root "/mnt/your_root".

Here is the point I want to make:

   You should install any additional SAM tarballs in
   /mnt/your_root/lib.  You can do this by putting the actual files in
   /mnt/your_root/lib or, better, put symlinks there to the installed
   tarballs.

File bprofile is important, because it takes care of two important
variables.  These are sam_temp_base and sam_set_version.  Default
values are provided in script begin, but you may override these values
in /mnt/your_root/bprofile.  See TIPS for more information.

Note how SAM differs from traditional software; you should not change
your PATH variable to include SAM executables.  Neither should you put
SAM exectables in dirs that are in your normal PATH.  See the section
below, Running SAM, to learn how to run SAM.


5.  Running SAM.

To run a SAM installation which is installed to /mnt/SAM_root,
simply invoke begin like this:

   /mnt/SAM_root/begin

The word "run" is a little misleading here.  There is code that is run
to begin SAM and to end SAM.  This code runs in the usual sense.  But
in between beginning and ending nothing is running, not even a daemon
or a process in the background.  SAM is similar to an old piece of
software for the Commodore 64 called the "DOS Wedge" in this way.  It
gets the work done not by running, but by changing how things run.  SAM
does this by manipulating the environment.  It changes the PATH
variable and other variables, and it sets and unsets variables and
functions.

I needed to explain this, but I will not talk about it anymore.  I will
use the word "run" in reference to SAM and expect you to understand
what it means.  Here, then, is what you need to know about "Running
SAM":

There are eight scripts that participate in running SAM.  They are:

   begin
   bgen
   bits
   bree
   breekit
   buser
   bxadd
   bxauth

You can find all of these in the root of an installed SAM distribution. 
Each has a different purpose.

I explained above how to invoke begin.  Script "begin" will run SAM in
the normal way.  It can be used when SAM is not running, or you can use
it again after you have already started SAM.  You will know that SAM is
running by the changed prompt.  (SAM has a two-line prompt.) To exit
from SAM enter "bye" or "exit".

You should use the full path when invoking these scripts.  I'm not sure
if this is necessary for all of them, but it is for at least a few, and
this therefore will avoid confusion.  Also, all but bxadd and bxauth
can be run as an ordinary user or as root, although the purpose of bree
and breekit is to become root, so you wouldn't ordinarily run these as
root.  Scripts bxadd and bxauth run xauth which belongs to X.  X
doesn't like root, so don't run them as root.

Here are explanations these scripts:


   begin          Runs SAM for ordinary users and root.  Nested
                  invocations (running SAM from inside SAM) are
                  allowed.  The resulting shell (nested or ordinary
                  invocation) inherits all exported variables plus
                  non-SAM exported functions.

   bgen           You should make symlinks to bgen in /mnt/your_root
                  directory.  Give these symlinks the names of any
                  script in $sam_root that you wish to use in dual
                  mode, but only symlinks "begin", "bree" and "breekit"
                  are necessary.  You can invoke the other scripts
                  directly.

                  Use the resulting symlinks in the same way that you
                  would use the corresponding scripts in $sam_root.

   bits           This script is used internally by SAM.  It enables
                  the managed invocation of three compiled executables
                  which SAM uses.  In particular it automatically
                  chooses between 32 and 64 bit versions that are
                  included in the SAM tarball.

   bree           Runs SAM again from an environment in which it is
                  already running.  The new instance becomes root and
                  inherits all exported variables plus functions that
                  were defined by SAM.  If there are any non-SAM
                  exported functions, these will be inherited also.

   breekit        Uses begin to run SAM, and then bree to run SAM
                  again, recursively, as root.  It inherits variables
                  and functions in the same way as begin.

                  Like begin, this script allows nested invocations,
                  however I can think of no reason you would want to do
                  this.

   buser          This script is for use in X on ZombieSlack
                  systems.  It enables the shell to use special
                  ZombieSlack functionality.  Doing so, it opens a
                  shell as another user.

                  ZombieSlack is another project of mine.  A
                  ZombieSlack system runs a specially tailored version
                  of Slackware.

   bxadd          Run this script from a remote X session after first
                  running bxauth, on a local X session.  It will give
                  you a local xterm which belongs to the remote
                  session.

                  Use $1 to provide the value of DISPLAY, less ":", for
                  the local session.  

   bxauth         See notes for bxadd.


6.  Using SAM.

After invoking SAM you will see that the prompt has been changed.  It
will look something like this:

   sam 1::)1
   student@220506aa1:/mnt/joe_root)

There is a lot of information in the two-line prompt, but I won't
describe it yet.  If you get a prompt that looks something like the
above, then you are in SAM.

The first command to learn is "menu".  Invoke the menu command.  You
should get a screen that begins like this:

   added:
   
   /mnt/SAM_root/lib/tool
   /mnt/SAM_root/main
   /mnt/SAM_root/kernel
   
   ::
   
    COMMAND       DESCRIPTION
   
   SAM is a flexible, text-based menuing system.
 
The menu name is normally displayed after the ":" above, but as there
is no menu currently defined the prompt shows "::".

Even though there is no menu, you can still tryit out.  Scroll up and
down with the up and down arrows.  (You are actually using the "less"
command.) Pressing "q" returns you to the command prompt.  Enter "menu"
to display the menu again.

One way to use SAM is to enter commands from the current menu to do the
things described by the menu.  This works, because the commands of the
current menu are added by SAM to the PATH.

This is the quintessential use of SAM.  The menu shows shows you what
the current commands are.  You may not remember them otherwise.  The
menu also describes how to use the commands.  This allows use of
commands that take multiple arguments: the text of the menu is a handy
reference that defines the use of $1, $2 and so on.  With a such a
reference readily available you can write and use code that is more
powerful than what you could manage otherwise.

SAM, however, makes many commands available, not just the commands of
the current menu.  Every use of the menu command, whether there is a
currently defined menu or not, will show a list of added paths.  These
are paths that have been added by SAM to the PATH.  They are listed
below "added:"

You can see above that there are currently three paths added.  The menu
shows their full names, but these names are equally valid:
"$sam_root/lib/tool", "$sam_root/main" and "$sam_root/kernel".  SAM
plays by its own rules.  It couldn't do the things it needed to do
without having the commands of "$sam_root/kernel" available.  Some of
these commands are handy for your own use as well.

There is no magic in the menu command, and very little code.  All it
does is display file $level/menu.dat.  However, that is just what is
needed.  I wrote a menu.dat file for the kernel.  You can see it, or
any menu, even when it is not current by this use of the menu command:

   menu $sam_root/kernel

This, instead of showing the current menu, displays a named menu.  Try
it and you will see that the menu command itself is listed and
described:

       menu       If $1 is "", displays current menu.  Otherwise
                  displays menu for $1.

Other commands of the kernel that you will surely use are "bound",
"bye" and "library".  These you may also find useful: "hello",
"library" and "shoparts".

Remember always to press "q" to leave a menu before entering a command.

Use "exit" to leave SAM.  This is not a SAM command.  It works by
exiting the shell that is keeping SAM open.  It is like pulling the
stopper from the bath tub--the water goes down the drain.

Use "bye" to leave a menu and return to the previous one.  When there is no
previous menu "bye" will take you all the way out of SAM.

Use ";" to separate commands on one line.  This is a feature of Bash,
not of SAM, but it works well in SAM.


6.1 The SAM prompt.

Here is a breakdown of the parts of the prompt:

   \n$sam_file:${level}${sam_symbol}${sam_env_num}$sam_env_num
   \n\u@\h:\w${sam_symbol} 

   The first line of the prompt has these parts:

      sam <instance>:${level}${sam_symbol}${sam_env_num}

         <instance>   SAM can be started a number of times by each
         user.  Theses "instances" of SAM are counted, and the current
         value of the count is displayed in the prompt.

         $level        This is the path which the user selected to
                       represent the current menu.

         $sam_symbol   This is defined by script $sam_root/go/sam where
                       it is defined as ")" and exported.

         $sam_env_num  Each instance of SAM uses a stack of
                       environments.  $sam_env_num is the current
                       position in the stack.

      Note: Internally, SAM represents the instance together with the
      name of the file ($sam_root/go/sam) which was used to start SAM. 
      This combination is referenced in SAM as "$sam_file".  Therefore
      $sam_file is

         sam <instance>

   The second line of the prompt is:

      \u@\h:\w${sam_symbol}

         \u            user

         \h            hostname

         \w            working directory

         $sam_symbol   <See above.>

   Except for the use of $sam_symbol at the end, this is probably
   familiar to you.

I apologize if you have grown accustomed to having the final character
be "#" for user root.  I chose not to implement that behavior, because
SAM allows you to become root in a number of different ways which vary
somewhat in their nature.  Note that, in my experience, \u shows the
same value as `whoami`.  Therefore, if you see "root" in the prompt, it
is probably safe to assume that you are root.  That's what I do.  I
have not found this documented anywhere.

Here is a table which summarizes the different ways to become root in
SAM.  See the Key and Note below also:

     `whoami`/$LOGNAME/$USER in console
   ---------------------------------------
   before       after     after
   starting     begin     begin, then bree
   --------     -----     ----------------
   O/O/O        O/O/O     R/O/O
   R/R/R        R/R/R     R/R/R

        `whoami`/$LOGNAME/$USER in X
   ---------------------------------------
   before       after     after
   starting     begin     begin, then bree
   --------     -----     ----------------
   O/O/O        O/O/O     R/R/O
   R/R/R        R/R/R     R/R/R

   Key: O=Ordinary user, R=Root user.

   Note:  Use of breekit gives the same results as "begin, then bree".


7.  About SAM menus.

A menu for sam is a file named "menu.dat".  Make one and put it in a
directory, and it will be displayed by the use of the command

   menu

when it is the current menu.  To make a menu current use the "bound"
command.

I will illustrate with an example, but first I need to mention my use
of the term "current".  Hopefully you are familiar with "current" as it
applies to directories.  I have given the term "current" a new use by
applying it also to menus.  When a menu is "current" that means that
variable level has been given the value of the path to the directory. 
SAM then knows to treat it in a special way.

A directory is current when you are in it.  You go into a directory by
using "cd".  That is nothing new.  A menu is "current" when you "bound"
to the path that defines it.

Here is an example:

   /mnt/SAM_root/begin
   echo test > /tmp/menu.dat
   bound /tmp
   menu
   bye
 
This example makes the menu at /tmp current ("bound /tmp" does this). 
The "menu" command causes the menu to be displayed, and "bye" will exit
SAM.


8.  Special variables.

This variable can be used to control the behavior of SAM.  Set it
anyplace and anytime:

   sam_batch

      Exporting sam_batch with value of batch (or anything) will cause
      SAM to be run in a batch mode.  In this mode it will not give you
      interactive behavior.  Sometimes interrupting a shell script
      results in an interactive shell opening at the point where the
      script stopped.  Often this is not desired.  Use this variable to
      prevent this behavior.

This variable also controls the behavior of SAM:

   export sam_view=<alternate menu viewer>
   
      You would export this to change the viewer which is used by
      $sam_root/kernel/menu to display menus.
   
      The default viewer is "less".
   
There are other variables that are important to SAM but are normally
dealt with by your $sam_root/bprofile.  Read about them in
$sam_root/TIPS.


9.  There is a nuisance that you might encounter.  This nuisance
happens when files in $sam_temp_dir (which points to the current temp
for SAM) gets files in it that cannot be written to.  Say for example
that you have a temp dir at ~/temp1, but you get a file in it that
belongs to root.

When this happens you will need to change to root, go to ~/temp1 (or
temp2, etc) and change the ownership of the files back to the user (not
root). Or you can leave SAM, clean out the $sam_temp_dir's, and try
again.


10.  SAM's temporary and scratch directories.

This tells the scheme for SAM's temporary and scratch directories.


$sam_temp_base    You can set sam_temp_base to anything you want, but
                  $sam_root/bprofile included with this distribution
                  sets it to:

                     /tmp/`whoami`

$sam_temp_dir     You can set sam_temp_dir to anything you want, but
                  $sam_root/go/sam included with this distribution sets
                  and exports it like this:

                     export sam_temp_dir=$sam_temp_base/temp${1}

temp<n>           temp1 - temp<n> are made by this line in
                  $sam/sam_core:

                     mkdir --parents $sam_temp_dir

                  Note that (in this distribution) this will also make
                  $sam_temp_base if it does not already exist.

$env_scratch      I believe (but I'm not sure) that you can set
                  env_scratch to anything you want, but
                  $sam_root/sam_env included with this distribution
                  sets and exports it like this:

                     export env_scratch=$sam_temp_base/scratch

scratch           Make scratch any way you like, but in this
                  distribution scratch is made by this line in
                  $sam_root/brc:

                     mkdir --parents $sam_temp_base/scratch

                  Note that this will also make $sam_temp_base if it
                  does not already exist.

Note that the number of temp<n> directories is limited mainly by the
way in which SAM is configured.  In the current distribution the
maximum number of directories is configured by the way in which
$sam_root/begin invokes $sam_distro/go/sam1.  In particular, the
maximum is $1.

temp<n> are known as $sam_temp_dir.


11.  Shells used

SAM uses #!/bin/sh in all* scripts except in case:

   Scripts that are to be sourced have no line beginning "#!".  And,
   they have read permission, but no execute permission.

I spent some time trying out SAM in Ubuntu.  In Ubuntu /bin/sh is a
link to dash.  SAM should work OK in Ubuntu if you first change that
link to point instead to the (traditional) bash.  Also you may need to
have a real root account.  There is a change you can make in Ubuntu to
do this.  I recommend it.  (Do "sudo passwd root" to get a real root. 
If you change your mind do "sudo passwd -l root" to lock root again.)

*One script ($sam/sam_core) has code that writes code to open
additional shells.  The code it writes uses "/bin/bash".  I chose
"/bin/bash" over "/bin/sh", because I wanted to use the --rcfile
option.  Using this option let me write better code, so I did it.  This
works in Ubuntu, but functionality in Ubuntu was not the reason for the
choice.


11.1  Synthetic shells  

Besides the normal Bash shell, SAM uses an oddity that I call a
"synthetic" shell.  I am fully responsible for it.  I invented it to
give SAM the behavior I desired.  Synthetic shells are coupled with
$sam_env_num in the same way that normal shells are coupled with
$SHLVL.  To help the user I gave SAM a prompt that displays
$sam_env_num at the end of the first line of SAM's two-line prompt. 
SAM needs the synthetic shell for it's operation, but you may interact
with it as well.  It works by pushing *some* of the current variables
onto a stack--which is actually a set of files in $sam_temp_dir--and
incrementing the variable sam_env_num.  To "pop" it decrements
sam_env_num and unsets, sets, and exports as needed to restore the
previous environment.  It's actually just a bit more complex than this. 
Look at the source code in sam/source to learn more.  In short, SAM's
synthetic shell works by manipulating the current environment.

Let me explain my use of the word *some* above.  SAM pushes variables
that begin with a lower case letter onto a stack.  And variables that
begin with some other characters too.  The C code that is operating
here (set_filt.exe) selects all variables (for pushing onto the stack)
that begin with a letter with an ACII value greater than 96.  If you
examine an ASCII table you will see that this includes a-z and some
unusual characters, but excludes A-Z.  The intention was to exclude
variables in all caps which are normally environment variables, but you
can see that by my lazy coding I excluded more than just these.


11.2 Some notes on scripting

SAM is script-able.  What you do at the command line you can put into
ordinary shell scripts.  I will not define the full scripting
capability, instead I'll just give you a few words of wisdom.

There are two kinds of scripts that SAM uses.  These are: (1)
undesignated, meaning not of the following kind, and (2) authorized
scripts with names that end in ".sam".  A script is "authorized" if it
contains the line "#OK SAM" somewhere in its first ten lines.

Scripts of the .sam kind are used to define functions.  Each such
script may define one function.  That function should have the same
name as the script less ".sam".  What is special about a
.sam script is that SAM makes the function it contains available when
and only when the directory that contains the script has been added to
PATH by use of SAM's commands.  In this way the functions in these
scripts can be used like executables in a directory.  Thus they fall
under SAM's menuing control.

I invented this feature (used when scripts ending .sam are referenced),
because some things can be done conveniently by functions than
otherwise.  Yet I needed the functions to behave like ordinary commands
for them to be useful to SAM.  In particular, functions are convenient
whenever it is desired that the result of the operation performed apply
to the current environment.  This is needed when coding a tool to
change current directories-- perhaps your tool uses "cd".  And it is
needed when your tool changes the local (SAM term) directory or the
current set of local or exported variables as you might do with the
bound or sam_shel commands.  I tried using "source" (or ".") to trick
ordinary scripts into doing this, but I got into a tangle (with
positional parameters) which made it difficult at best.

The current method works, but be aware of what's happening.  If you
want to investigate, see files $sam/dofun, $sam/upfun.sam, and
$sam_temp_dir/unfun.

You may write and use your own scripts of both kinds.


12.  SAM.tool

This distribution is equivalent to SAM.base with SAM.tool installed.

This installation of SAM.tool was done by simply unpacking SAM.tool to
$lib.  This makes and populates directory $lib/tool.

The commands of $lib/tool are documented in its menu.  You can read the
menu with this command:

   menu $lib/tool

And you can change to the menu with this command.

  bound $lib/tool
