SAM Kernel
Updated 8-18-11

Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011 Joseph Rosevear


SAM is the paradigm that is born of the union of a SAM kernel and
application.  The application brings much to SAM, but the essential
nature of SAM is defined by the kernel.  That is what I will describe
here.

Read this guide, but also use other ways to learn about SAM. Just
trying and doing is a good way.  Also you can look at the scripts from
which the SAM kernel is made.  There aren't very many.  There are three
C language executables.  You can look at their source files.  The
examples and explanatory files that may have come with your SAM program
are an excellent way to learn about SAM too.

Another way to learn about SAM is to run it in debug mode. When you do
this you will see messages that tell where SAM is in its execution and
a little about what SAM is doing.  SAM will also run more slowly to
give you time to read the messages as the appear on the screen.  To use
debug mode type "export sam_debug=on".  Then use SAM in the normal way. 
It is helpful to write down the comments so that you can then study
what SAM did.  To leave debug mode type "unset sam_debug".

Here is the guide:


1.  The terms "local" and "current"

SAM and its documentation use the terms "local" and "current".  The
term "current" is used in its familiar way as in "current directory". 

The term "local", however, belongs to SAM.  It is not the same as
"current".  Any directory can be made local.  The "bound" command in
the global menu can be used to do this.  When you use bound $1 is added
to PATH and the file $1/menu.dat is displayed (if it exists) along with
other text.  This is what is meant by "local".

The other text displayed describes the global menu which corresponds to
the commands of the $sam and $sam_tool directories.  These directories
have their own files menu.dat which are used when the global menu is
displayed.


2.  The "bound" command

When you use "bound" you will want to name a complete path that goes to
a directory where you have programs (scripts, executables or functions)
that you want to use.  This way you can easily document (briefly) what
the programs do and how to use them (in the menu), and you can easily
put your programs in separate directories without the need to have the
paths to these directories always in your PATH variable.

SAM takes care of the PATH variable, adding to and subtracting from it
in a way that is consistent with its use.  SAM displays both the local
directory and the current directory in its prompt.  Try using the
command "bound" to see this.


3.  SAM's shells  

SAM displays a shell counter, a numeral, at the end of the first line
of the prompt.  SAM uses one genuine Bash shell.  The other shells that
SAM makes are "synthetic".  SAM needs these synthetic shells for it's
operation, but you may interact with them as well.  The synthetic shell
works by "pushing" 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.  You should understand that SAM's synthetic shells work by
manipulating the current environment.


4.  Some notes on scripting

SAM is script-able.  What you do at the command line you can put into
ordinary shell scripts.  This guide will not define the full scripting
capability, instead it will make a few notes.

There are three kinds of scripts that SAM uses.  These are: (1)
undesignated, meaning not one of the following two kinds, (2)
authorized scripts with names that end in ".f", and (3) 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 .f and .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 the ".f" or ".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.  The scripts ending in .f are a bit
different.  Read on.

This feature (used when scripts ending in .f or .sam are referenced)
was invented, because some things can be done conveniently by functions
that cannot be done 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 the
source (or ".") command to trick ordinary scripts into doing this, but
I got into a tangle (with positional parameters) which was difficult if
not impossible.

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

The ".f" scripts still need to be clarified.  Unlike commands in ".sam"
scripts, the commands from ".f" scripts remain available until you exit
from the environment in which they were defined.  This was invented for
commands defined by functions in $sam and $sam_tool, since it is
desired that these commands remain available throughout the SAM
session.

You may write and use your own scripts of all three kinds.


4b.  Batch mode

SAM has a batch mode.  It is selected by exporting thusly:

   export sam_batch=batch

before invoking SAM.  In batch mode a shell will not stay open waiting
for a command line input.  This capability was added to SAM to allow me
to invoke it from crontab files.  It wouldn't work otherwise.

See $sam/sam_core for the details.


5.  Bugs in SAM

recursion:

You can invoke SAM inside of SAM, but there is one peculiarity when
doing so.  The functions that were defined before the nested SAM was
invoked will be inherited by the nested SAM.  That is they will be
unless something is done before SAM is invoked.

This is either a feature of SAM or a bug.  It is something that you
should be aware of.

SAM is written so that you can easily remove the existing function
definitions.  This guide is not about the application of SAM, but you
can be sure that any application of SAM that I write will automatically
remove inherited function definitions.  Still, you should be aware of
this, and be careful.

lockfile and msdos:

SAM uses the lockfile command to augment the protection given by the
use of the "in_use" file.  The in_use file protects against multiple
simultaneous uses of the same $sam_temp_dir, however it fails at this
when the user invokes SAM rapidly in succession.  That's where the
lockfile command comes in.  It almost fixes things.  The problem is
that I haven't been able to get lockfile to put a lock on a file in an
msdos file system.  There is no such trouble with the native Linux ext2
file system, so maybe this is a non-issue.

SAM tries to put the lock file in sam_temp_dir.  So if you are using an
msdos file system for $sam_temp_dir, be aware that there is no
protection against rapid successive invocations of SAM causing multiple
simultaneous use of a $sam_temp_dir.  You will see a warning from
lockfile that it cannot do it's job--something about praying.  If you
avoid rapid successive invocations of SAM when using $sam_temp_dir in
an msdos file system you'll be OK.


6.  SAM limits

SAM has some limits that might be seen as bugs as follows:

Don't run instructional text files:

Be careful not to run instructional text files (such as this file). 
BAD things could happen.  Ordinarily such files cannot be run, because
they don't have execute permission.  However, if you run SAM from an
msdos file system, then you will not have this protection.  Or this
could also be the case if I (or someone) have given a text file execute
permission by mistake.

Beware commands and variables:

SAM has a few scripts and executables that you may not know about
unless you look.  They are not likely to do any harm, but it would be
smart for you to look and see what they are so you don't use them by
accident.  The documentation does not currently list all the scripts
and executables.

Similarly, SAM adds many variables to the environment.  It does this in
a shell, so you original environment is protected.  However, SAM
depends on these variables to do what it does.  You could have
difficulty if you alter one of them.  The documentation does not
currently list these variables.
  
cd `pwd`:

SAM does this (the above) in sam/pop.f.  It is an odd thing to have to
do.  It is needed to make the prompt correct in certain situations, but
this isn't fully understood.

Disk space:

You can run out of disk space needed for SAM's $sam_temp_dir.  Although
this isn't likely, SAM does nothing to prevent it.  It would cause SAM
to fail.

Limited buffers:

A buffer in set_filt.c is of limited size and can cause failure.  The
code checks to prevent writing beyond the end of the buffer, but
unfortunately SAM cannot proceed if the buffer isn't big enough.  See
the source code for details, and be aware that this error message

   Buffer size exceeded.

means the buffer size limit has been encountered.  You are free to
change the buffer size and recompile.

Non existent local directories:

SAM doesn't care if you do this:  "bound /hey".  It works whether /hey
exists or not.  This is good, because SAM is a tool.  You may have a
reason to do this even if /hey doesn't exist.  Similarly, you can do
this: "bound hey".  The leading "/" has been removed.  Again you may
have a reason to do this.  In both cases if you aren't aware of what
you are doing, SAM may surprise you.

Mistakes of comprehension:

When writing SAM scripts you are really writing ordinary Bash shell
scripts.  Yet, there are mistakes of comprehension that can be made. 
It is easy to misunderstand what SAM does.  The methods of scripting
shown by the examples (that may have come with your distribution) work
well when each method is understood and followed.  If a method is not
followed, then it may not work correctly.  Similarly, if a method is
not understood, it may seem to not work correctly.  Both situations can
be frustrating, but such are not necessarily errors belonging to SAM.

Limitation in xargs:

SAM puts a lot of stuff in the environment.  In particular, it exports
a lot of variables and functions.  This is why I sometimes got an error
message which said "xargs: environment is too large for exec".  The
solution I found was to change xargs and recompile it, then replace the
original xargs with the corrected one.

Here's the piece of code I changed, before and after:

   Before:

      if (arg_max > 20 * 1024)
        arg_max = 20 * 1024;

   After:

    /* JHR 050813 I commented out and changed the two lines below */
    /*if (arg_max > 20 * 1024)
        arg_max = 20 * 1024; */
      if (arg_max > 40 * 1024)
        arg_max = 40 * 1024;

I learned that this was the needed fix by what I found when searching
in Google Groups "www.groups.google.com" on the quoted error message.

After doubling the limit (from 20K to 40K) I've had no trouble...yet.
