\input texinfo   @c -*-texinfo-*-
@c %**start of header
@c Part 1: Header
@c --------------
@c The header does not appear in either the Info file or the printed
@c output.  It sets various parameters, including the name of the Info
@c file and the title used in the header.
@setfilename salmon.info
@settitle Salmon Spawning A Process Via Exec Functions
@documentlanguage en_US
@documentencoding UTF-8
@paragraphindent 0
@dircategory Individual utilities
@direntry
* Salmon (salmon).              Exec Functions - Tutorial
@end direntry
@c %**end of header

@c Prevent so-called standard-typography double-spacing after end-of-sentence.
@c Double-space-at-end-of-sentence was standard in the age of manual 
@c typewriters, but we're 40 years beyond that now.
@frenchspacing on

@c ---------------------------------------------------------
@c Define macros for often-used or occasionaly-updated text.
@c ---------------------------------------------------------
@c (copyright years)
@macro CRYEARS
2012-2026
@end macro
@c (( version)
@macro SPVERSION
0.0.05
@end macro

@c Macros shared among all Texinfo documentation projects.
@include texi_macros.texi


@c Part 2: Summary Description and Copyright
@c -----------------------------------------
@c *Note GNU Sample Texts::. for more information.
@copying

@smalldisplay
@group
Copyright @copyright{} @CRYEARS 
@w{             } Mahlon R. Smith, The Software Samurai

This manual describes version @SPVERSION of 'salmon'.

  Permission is granted to copy, distribute and/or modify this document
  under the terms of the GNU Free Documentation License, Version 1.3
  or any later version published by the Free Software Foundation;
  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
  Texts.  A copy of the license is included in the section entitled 
  "GNU Free Documentation License".
@sp 2
@end group
@end smalldisplay

@end copying

@c Part 3: Titlepage, Contents, Copyright
@c --------------------------------------
@c The titlepage segment does not appear in the online output, only in the
@c printed manual.  We use the `@insertcopying' command to include the
@c permission text from the previous section, instead of writing it out
@c again; it is output on the back of the title page.  The `@contents'
@c command generates a table of contents.
@titlepage
@title Exec Library Functions - Tutorial (salmon)

@c The following two commands start the copyright page.
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage

@c Output the table of contents at the beginning.
@contents

@c Top Node and Master Menu
@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ifnottex
@node Top
@top Exec Library Functions - Tutorial (salmon)

@insertcopying
@end ifnottex


@menu
* Introduction::                 Multiple Processes, One App
* Invoking::                     Command-line arguments and options
* Are You My Mother?::           Gathering information about the terminal
* Building from Source::         Compile the application
* gString Text Tool::            Text Internationalization and formatting tool
* Technical Support::            Make suggestions, report problems.
* Copyright Notice::             Boring, but useful.
* Index::
@end menu


@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c 01.0 Introduction:    - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c      Multiple Processes, One App  - - - - - - - - - - - - - - - - - - - - - -
@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node Introduction
@unnumbered Introduction
@cindex 01.0 Introduction

The @t{'Salmon'} application is a GNU/Linux console (command-line) utility which 
demonstrates some common examples of spawning an external process from within 
an application.

Because this is a demonstration program only, the logic is straightforward but 
not comprehensive. A production-worthy application will give much more attention 
to possible error conditions. Also, the documentation (this document) is quite 
simple, but we hope you will find it useful.

Also, we apologize for the application name, but we couldn't resist. 
This project was written strictly for fun. @LDQ{}Salmon@RDQ{} swim upstream 
to spawn fish eggs, not process @t{IDs}, but we hope you get the idea.
@sp 1

@H5heading{Note to novice programmers:,
           ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔}
This application is written in C++, but it discusses various C-language 
primitive functions. When we use the word @t{"@b{function},"} we mean a C-language 
routine. When we use the word "method," we mean a C++ routine. This difference 
in terminology may seem to be a small one, but wars have been fought over it. 
(We are geeks, after all.) Since Software Sam is a teacher, prepare yourself 
for a boring explanation:@*
A C-language "function" @emph{does something} (moves the program flow from point 
A to point B), while a C++ @LDQ{}method@RDQ{} @emph{accomplishes something} 
(solves a problem) within a class or object. This is tied to the concept of 
object-oriented programming as contrasted with the so-called @LDQ{}structured@RDQ{} 
programming that was common in the days when dinosaurs roamed the earth. 
(And that doesn't @b{@i{begin}} to describe the spaghetti code written by the 
Neanderthals in the UNIX world!)
@sp 1

@H5heading{The "Exec" Family Of Functions,
           ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔}
@enumerate A
@item This application is intended as a reference for students and others 
who want to understand the use of the @t{"@b{exec}"} group of primitive 
functions and other functions related to spawing a child process from 
within a parent application.

The Salmon package includes source code for two executable binary files, 
@t{'Salmon'} and @t{'childApp'.} Salmon contains the interesting code which 
invokes @t{childApp} with various arguments. @t{childApp} simply reports the 
arguments it has received from the controlling application, then termnates.

@item The @t{"@b{exec}"} function group invokes an external program.

   @enumerate 1
   @item If the @t{exec} call is successful, then the process @t{ID} used 
   to invoke the external program will terminate when the called application 
   or script exits.

   @item If the calling @t{PID} is the only process @t{ID} running in 
   the calling application, then the calling application terminates 
   immediately when the @t{'@b{exec}'} function is called.

   @item If multiple process @t{IDs} are active when the external application 
   is called, then only the process which executes the @t{'exec'} function 
   is detached from the calling application and will eventually terminate 
   while the remaining processes will continue to execute within the calling 
   application. See the description of the @t{"@b{fork}"} function, below 
   for more information.

   @item An external application could be a web browser, email client, 
   image viewer, etc. It may or may not write to the terminal window 
   from which it was launched. If it does, it will overwrite the display 
   data of whatever application is already running in that window, so be 
   aware, and capture the output if necessary.
   @end enumerate

@item Technical Note: Do not confuse the creation of multiple, independent 
processes with the concept of @b{@i{multithreading}}. Processes and threads have 
significant differences in terms of resource allocation and scope of access. 
To perform multiple tasks within a single application, we strongly recommend 
multithreading rather than creating multiple processes. 

Multithreading is an operation in which multiple execution threads 
@i{(paths of execution)} are created, and each is launched into its own 
private method to perform a specific task. The creation, use of and 
termination of programatic threads is not covered in this example application.@*
Please see our @t{"@b{Sew}"} @i{(as in @LDQ{}Sew, a needle pulling thread@RDQ{})} 
application for a demonstration of multithreading.

@item The @t{"@b{fork}"} function creates a split in a program's flow of execution.

   @enumerate 1
   @item The @t{"@b{fork}"} group of functions is used to create a child 
   process within the calling application. For the "fork" function, the 
   parent and child processes initially have identical copies of the 
   application environment (the @t{"@b{process image}"}). See the @t{"fork"} 
   function documentation (@t{info fork}) for exactly what is included in 
   this process image.

   Note that for this application, we want the forked process to immediately 
   execute an external process. For this reason, we use the @t{"@b{vfork}"} 
   function rather than @t{"fork"} because @t{"vfork"} does not create an 
   unnecessary copy of the process image which will be immediately discarded 
   anyway. Instead, the @t{"vfork"} function allows the parent and child 
   to @b{@emph{share}} the single process image for the short time they are 
   running concurrently in the parent application.

   @item The parent process continues to execute the calling application.
      @enumerate a
      @item This process may immediately continue, OR
      @item the process may sleep using the @t{"@b{waitpid}"} function 
      until the child process terminates.
      @end enumerate
   @end enumerate

@item The child process @b{@emph{also}} continues to execute within the 
calling application; @b{@emph{however}}, its actions must be strictly 
limited to avoid destruction of the calling application's data and environment.

   @enumerate 1
   @item When an application spawns a child process using @t{"@b{vfork}"}, 
   that process needs something to do. That @LDQ{}something@RDQ{} must 
   not interfere with the operation of the parent process.

      @enumerate a
      @item It may not modify the environment (with certain exceptions)
      @item It may not change variable values (with certain exceptions)
      @item It may not gather input nor produce (asynchronous) output 
      which conflicts with the parent process.
      @item Perhaps most importantly, the child may not allocate or 
      release stack space. In practical terms, this means that the child 
      process must @b{@i{NEVER}} return from the method in which it was spawned.
      @end enumerate

   @item Resource conflicts for the input/output streams, 
   @t{'stdin', 'stdout'} and @t{'stderr'} may occur between the parent 
   and child processes. To avoid resource conflicts with console 
   applications or scripts launched by the child process:

      @enumerate a
      @item The child process will avoid capture of input and will produce no 
         output to the standard streams, @t{'stdout'} and @t{'stderr'}. 
         Note that this is not always practical, and must be handled carefully. 
         Either the called executable was written by you, and is therefore 
         guaranteed to generate no @t{I/O} to the shared streams, or it must have 
         a @t{"silent mode"}, similar to our @t{'cTrash'} utility in which 
         all I/O is redirected to either temporary files or to a block of 
         static memory. (see @t{"dup2"} below)

      @item The parent process sleeps until the child process terminates.@*
         See the @t{'-f'} option (@ref{Invoking}) for an example.

      @item Input (stdin) and output (stdout and stderr) for the child process 
         may be redirected, which allows the parent process to retain control 
         of stdin, stdout and stderr.@*
         See the @t{'-s'} option (@ref{Invoking}) for an example.

         @itemize @EMDASH
         @item Typically, any startup messages of an external 
         (non-console) application can be discarded by redirecting 
         @t{'stdout'} and @t{'stderr'} to temporary files.@*
         This redirection can be accomplished by using the @t{"@b{dup2}"} 
         function.

         @item The @t{"@b{dup2}"} redirection method may also be used 
         to capture any output produced by the child process which may 
         be needed later.

         @item For simple external calls when the output is not needed, 
         the output can be redirected to the @LDQ{}bit bucket@RDQ{}.@*
         The bit bucket consists of a device, @t{'/dev/null'} which 
         simply discards whatever is sent to it. Note that this is a 
         shared resource.

         @verb{|   Command-line Example:|}@*
         @verb{|      echo $PWD 1>/dev/null 2>/dev/null|}@*
@c         @verb{|      echo $PWD 1>/dev/null 2>&1|} @ @ (fancy :-)@*
         @verb{|   Example using 'system' function call:|}@*
         @verb{|      system ( "echo $PWD 1>/dev/null 2>/dev/null" ) ;|}
         @end itemize

      @item The child process could be launched in a new terminal window.@*
      Note that this is an advanced operation which may not be transparently 
      supported by all terminal emulators and/or shell programs.@*
      See the @t{'-t'} option (@ref{Invoking}) for further discussion and 
      examples.
      @end enumerate
   @end enumerate
   
@item When specifying the location of the application called through 
one of the @t{'exec'} functions, the first argument is one of the following:

@verbatim
  1) A relative filespec:
     execv ( "./childApp", ... ) ;
  2) An absolute filespec:
     execv ( "/home/sam/SoftwareDevelopment/Salmon/childApp", ... ) ;
  3) The name of a file which can be found on the system $PATH:
     execv ( "grep", ... ) ;
@end verbatim

In the @t{Salmon} test application, both the calling app, @t{'salmon'} and 
the called app, @t{'childApp'} are located in the same directory, so a 
relative filespec would work as expected so long as @t{'salmon'} is 
invoked within the currrent working directory (CWD).@*
@verb{|   [Salmon]$ |} @b{@t{./salmon -v}}@*
In the real world, however, things are not always so simple. For this reason, 
an absolute filespec is used, so that even if @t{'salmon'} is not in 
the CWD, @t{'childApp'} will still be found. For example:@*
@verb{|   [Documents]$ |} @b{@t{../SoftwareDesign/Salmon/salmon -v}}@*
To understand how this is done, please examine the @t{getBasePath()} 
method in @t{Salmon.cpp}.
@end enumerate

@sp 2


@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c 02.0 Invoking - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c      Command-line arguments and options - - - - - - - - - - - - - - - - - - -
@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node Invoking
@unnumbered Invoking
@cindex 02.0 Invoking
@cindex invoking

@b{@verb{|   ./salmon -[v | l | p | f | s | t | D] [ARG1[ ARG2[ ARG3[ ARG4]]]] |}}@*
@b{@verb{|              | [--version | --help] |}}@*

@section Required Options

To invoke the application, specify one of the required options. plus zero or
more optional arguments.

Examples:@*
@verb{|   ./salmon -v|}@*
@verb{|   ./salmon -t 80 25|}@*
@verb{|   ./salmon --version|}@*

If no options are specified, the @t{"--help"} option is the default.
@hr90

@section Optional Arguments ARG1 through ARG4
These optional comand-line arguments are recognized by the 
@t{'-v', '-l', '-p', '-f'} and @t{'-t'} options.

For tests @t{'@b{-v}', '@b{-l}'} and @t{'@b{-f}'}, the specified arguments will simply be
passed to the child application (@t{childApp}) which will then display them 
to verify that they were passed successfully:

@verbatim
./salmon -l 'catsup is red' 'mustard is yellow' 'pickles are green' 'onions stink!'

    will yield:

Salmon Swim Upstream To Spawn!
 Invocation: "./salmon -l 'catsup is red' 'mustard is yellow' 'pickles are green' 'onions stink!'"
 Parent PID: 6201
 calling execl( childApp ... )

 childApp: PID: 6201
 ====================
 argv[0] childApp
 argv[1] -l
 argv[2] catsup is red
 argv[3] mustard is yellow
 argv[4] pickles are green
 argv[5] onions stink!
@end verbatim

Test @t{'@b{-p}'} calls the @t{'grep'} utility to scan for a specific text string 
within a specific source file. Therefore, any optional arguments provided 
will be interpreted as arguments for invoking @t{'grep'}. See the example below.

Test @t{'@b{-t}'} interprets any optional arguments as parameters for configuring 
the launch of a child window. See the example below.
@hr90

@section Invocation Options
@anchor{test -v}
@cindex test -v, execv
@cindex execv, test -v
@itemize @bullet
@item @b{@t{-v}} @ @ execv() function@*
Pass an argv[] array to childApp (calling application terminates).

The @t{'v'} in @t{"execv"} indicates the @t{argv[]} vector array, and 
as a software designer, you may be aware that this is an array of char pointers:@* 
@b{@verb{|   char const* argv[]|}}@*
with the last pointer in the array being the NULL pointer.

@example
Example:
--------

const char* fileName = "./childApp" ;
char const* argV[] = 
@{
   "This is argv[0]",   // this should be the bare filename of 
                        // the target (no path component)
   "This is argv[1]",   // additional arguments . . .
   "This is argv[2]",
   "This is argv[3]",
   "This is argv[4]",
   NULL                 // null pointer terminates the array
@} ;

execv ( fileName, argV ) ;
@end example
@spi

@c -------------------------------------------------------------------------------
@anchor{test -l}
@cindex test -l, execl
@cindex execl, test -l
@item @b{@t{-l}} @ @ execl() function@*
Pass a list of individual arguments to childApp (calling application terminates).

The @t{'l'} in @t{"execl"} indicates a list (sequence) of individual arguments, 
with the last item in the list being the NULL pointer.

@example
Example:
--------

const char* fileName = "./childApp" ;

execl ( fileName,             // path/filename of target application  
        &filename[2],         // should be bare filename of the target
        "This is argv[1]",    // additional arguments . . .
        "This is argv[2]",
        "This is argv[3]",
        "This is argv[4]",
        NULL                  // null pointer terminates the list
      ) ;
@end example
@spi

@c -------------------------------------------------------------------------------
@anchor{test -p}
@cindex test -p, execlp
@cindex execlp, test -p
@item @b{@t{-p}} @ @ execlp() function@*
Pass a list of individual arguments which invokes an application on the 
system PATH. (calling application terminates)

The 'l' in "execlp" indicates a list (sequence) of individual arguments, 
and the 'p' indicates that the directories specified by the $PATH 
environment variable will be searched for the application to be invoked.

Note that if the forward-slash character ( '/' ) is found in the 
application name, then the string will be interpreted as an absolute or 
relative path, and the $PATH variable _will not_ be searched. 

For this example, the external application called is the 'grep' utility.
'grep' is called with arguments describing what to search for and which 
file(s) to search.

@verb{|            grep -n 'COMPILE' Makefile|}

@example
Example:
--------

execlp ( "grep", "grep", "-n", "COMPILE", "Makefile", NULL ) ;

Note that each argument to execlp() is a separate string.
@end example
@sp 1

This test can accept optional arguments which are interpreted as arguments 
for invoking the @t{'grep'} utility, replacing the default arguments 
shown above.@*
The first optional argument will be interpreted as the search string, 
while the remaining optional arguments will be interpreted as the names 
of the files to be searched.

@verbatim
  Examples:
  ---------

  ./salmon -p fish Salmon.cpp
     yields:
     execlp ( "grep", "grep", "-n", "fish", "Salmon.cpp", NULL ) ;

  ./salmon -p '[#]define' Salmon.hpp GlobalDef.hpp
     yields:
     execlp ( "grep", "grep", "-n", "[#]define", "Salmon.hpp", "GlobalDef.hpp", NULL ) ;

  ./salmon -p Copyright Salmon.[hc]pp GlobalDef.hpp
     yields:
     execlp ( "grep", "grep", "-n", "Copyright", "Salmon.[hc]pp", "GlobalDef.hpp", NULL ) ;
@end verbatim
@spi

@c -------------------------------------------------------------------------------
@anchor{test -f}
@cindex test -f, execl
@cindex execl, test -f
@item @b{@t{-f}} @ @ execl() function executed by "forked" process.@*
The primary process calls the @t{"fork"} (actually @t{"vfork"}) function 
to create a child process, then the child process invokes an external 
program (@t{childApp}) which produces some output, then exits.

After calling @t{"vfork"}, the parent process waits silently for the child 
process to terminate, at which time it reclaims control of the I/O 
streams.

@example
Example:
--------

pid_t fpid = vfork () ;    // create the child process

if ( fpid == ZERO)         // the child process (if created) executes here
@{
   execl ( "./childApp",   // target application path/filename 
           "childApp",     // argv[0] bare target app filename
           "-f",           // argv[1] additional arguments . . .
           "some arg",     // argv[2] 
           "some arg",     // argv[3]
           "some arg",     // argv[4]
           "some arg",     // argv[5]
           NULL
         ) ;
 
   // In case the exec call fails: child process MUST NOT return,
   // so we force it to exit immediately.
   _exit ( 0 ) ;
@}
else                       // the parent process continues execution here
@{
   if ( fpid > ZERO )      // child successfully launched
   @{
      int childStatus = ZERO ;   // receives child's exit status
      int statusOptions = ZERO ; // status bitmask (none defined at this time)

      // sleep until the child process terminates
      waitpid ( fpid, &childStatus, statusOptions ) ;
   @}
   else
   @{
      // creation of child process failed
   @}
@}
@end example
@spi

@c -------------------------------------------------------------------------------
@anchor{test -s}
@cindex test -s, execvp
@cindex execvp, test -s
@item @b{@t{-s}} @ @ execvp() function executed by @LDQ{}forked@RDQ{} process.@*
The primary process calls the @t{"fork"} (actually @t{"vfork"}) function to 
create a child process, then the child process invokes an external 
program (@t{childApp}) which produces some output, then exits.

After calling @t{"vfork"}, the parent process continues execution immediately.

For this example, the output streams (@t{'stdout'} and @t{'stderr'}) of the 
child process are redirected to temporary files @t{'stdout.txt'} and 
@t{'stderr.txt'}, respectively. This allows the parent process to retain 
control of the output streams, even though both processes are 
simultaneously executing programs in the same terminal window.

After the child process has terminated, the parent process will copy the 
contents of the two temporary files to the display so the user can 
verify that the redirection was functioning properly.

@example
Example:
--------

const char* childApp = "./childApp" ;// name of app that child invokes
const char* childArgs[] =            // child's argv[] array
@{
   "childApp",          // argv[0] bare target filename
   "-s",                // argv[1] option switch from invocation of parent
   "Hello stdout!\n",   // argv[2] written to stdout (which is redirected)
   "Hello stderr!\n",   // argv[3] written to stderr (which is redirected)
   NULL                 // terminate the list
@} ;
const char* soFName = "./sout.txt" ; // stdout target file
const char* seFName = "./serr.txt" ; // stderr target file
int soDesc = ZERO,                   // file descriptor for stdout target
    seDesc = ZERO ;                  // file descriptor for stderr target

pid_t fpid = vfork () ; // create the child process

if ( fpid == ZERO)      // the child process (if created) executes here
@{
   // Create the temporary files.
   soDesc = open ( soFName, O_WRONLY | O_CREAT | O_TRUNC, 
                   S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) ;
   seDesc = open ( seFName, O_WRONLY | O_CREAT | O_TRUNC, 
                   S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) ;

   // Redirect 'stdout' and 'stderr' streams to the files.
   dup2 ( soDesc, STDOUT_FILENO) ;
   dup2 ( seDesc, STDERR_FILENO) ;

   // Close the temporary files.
   close ( soDesc ) ;
   close ( seDesc ) ;

   // If execvp() call is successful, the child process will not 
   // return to the parent application, else the return value 
   // will be written to stderr (which has been redirected to serr.txt).   
   wcerr << execvp ( childApp, (char* const* )childArgs ) ;
   wcerr << " Error! Child process call to execvp() failed." << endl ;

   // In case the exec call fails: child process MUST NOT return,
   // so we force it to exit immediately.
   _exit ( 0 ) ;
@}
else                    // the parent process continues execution here
@{
   if ( fpid > ZERO )   // child successfully launched
   @{
      wcout << L"Fork of child process was successful!" << endl ;
   @}
   else
   @{
      wcout << L"Creation of child process failed!" << endl ;
   @}
@}
@end example

@c -------------------------------------------------------------------------------
@anchor{test -t}
@cindex test -t, execlp
@cindex execlp, test -t
@item @b{@t{-t}} @ @ execlp() function executed by "forked" process.
The primary process calls the @t{"fork"} (actually @t{"vfork"}) function 
to create a child process, then the child process opens a new terminal 
window and invokes an external program (in this case, @t{grep}) within 
the new window.

The layout of the parameters for the call to @t{'execlp'} are described 
below. 

After calling @t{"vfork"}, the parent process continues execution immediately.

In the Salmon source code, we perform some magic to:

@enumerate a
@item determine the name of the terminal emulator program which is 
currently running,
@item determine the name of the shell program running in the terminal window,
@item calculate the size and position for the new terminal window.
@end enumerate

Please @pxref{Are You My Mother?} for a discussion of this practical magic.
@sp 1

@H5heading{Terminal Emulators and Shell Programs,
           ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔}
Terminal emulator applications share the common function of providing a 
command-line interface for exploring and configuring the more esoteric 
corners of the host system. 

In the beginning, the UNIX gods created the heavens and the @t{XTerm}. 
Until @t{GUI} interfaces were invented @t{XTerm} @emph{was} the user 
interface. 
While @t{XTerm} was, and is a marvellous creation, the command-line concept 
has, over time, evolved in several different directions. In the GNU/Linux 
world, the two most popular offshoots of @t{XTerm} are GNOME terminal 
(@t{gnome-terminal}) and @t{KDE Konsole} (@t{konsole}).

This test supports identification, configuration and invocation of these 
three terminal emulator programs:@*
@verb{|   a) gnome-terminal|}@*
@verb{|   b) konsole|}@*
@verb{|   c) xterm|}

The default configuration for this test is to launch a small terminal 
window, of the same type as the existing window, but centered in the screen. 
Optional argument, if provided, may be used to adjust some parameters.@*
@xref{Terminal Configuration} below for details.
@sp 1

@H5heading{Constructing the Commands for Launch,
           ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔}
Each terminal emulator program has its own invocation syntax and although 
they share the same basic functionality, there are some differences which 
need to be considered.

The most obvious is that @t{'gnome-terminal'} and @t{'konsole'} support 
tabs (multiple sub-windows), while @t{'xterm'} does not.

Another difference is that neither @t{'gnome-terminal'} nor @t{'konsole'} 
support window positioning under Wayland. XTerm continues to recognize 
horizontal and vertical offset parameters.

The configuration parameters for launching a new instance of the terminal 
window vary slightly depending on the emulator invoked; however, the following 
parameters are included:

@enumerate a
@item geometry:@*
The @LDQ{}geometry@RDQ{} for a window includes the window width in columns, 
and window height in rows. plus the horizontal and vertical offset (in pixels). 
As mentioned above, each emulator has its own way of handling geometry 
parameters; whether to accept, reject or ignore them.

@item working directory:@*
This is the directory which will be the Current-Working-Directory (CWD) 
when the window is opened.

@b{Technical Notes:}@*
By default, the @t{'gnome-terminal'} working directory is taken from 
the parent's $PWD environment variable. The CWD may be specified explicitly, 
either as an absolute path or via the environment variable.@*
@verb{|   --working-directory='/home/sam/SoftwareDesign'|}@*
@verb{|   --working-directory='$PWD'|}@*
@verb{|   --working-directory='$HOME/temp'|}@*
The @t{'konsole'} working directory is specified in its profile (generally 
the @t{$HOME} directory, so we must explicitly redirect it to the PWD:@*
@verb{|   --workdir='$PWD'|}@*
By default, the @t{'xterm'} working directory is the @t{$HOME} directory, 
but a child window will @emph{probably} reference the @t{'$PWD'} environment 
variable. XTerm has no command to directly specify the target working directory, 
so if a reliable CWD is needed, then the change-directory (@t{'cd'}) 
command must be integrated into the command sequence. Example:@*
@verb{|   -e bash -c "cd $PWD ; ls -l ; exec bash"|}

Note that the tilde character (@t{'~'}), used by the shell as a shortcut 
for the @LDQ{}Home@RDQ{} directory @emph{IS NOT} recognized in these contexts.

@item command sequence:@*
This is the command or sequence of commands to be executed within the new 
window. The syntax for this sequence varies according to the emulator and 
shell program used. Study the source code for the @b{@t{Test_Fork_execlp}} 
method to compare each emulator's invocation syntax.
@end enumerate

The following example describes the parameters for the @t{'execlp'} call.
This example uses the @t{gnome-terminal}, but other emulators have a similar 
syntax.
@verbatim
execlp ( 
   "gnome-terminal",           // name of terminal program (on system $PATH)
   "gnome-terminal",           // argv[0] (bare program name)
   "--window",                 // argv[1] (target is new window, not tab))
   "-q",                       // argv[2] (no output to parent window)
   "--hide-menubar",           // argv[3] (disable the  window's menu bar)
   "--geometry=65x9+400+300",  // argv[4] (size and position for new window)
   "--working-directory=trgdir"// argv[5] (target working directory)
   "-e",                       // argv[6] (the execlp 'execute' command)
   "bash -c \"grep -n 'COMPILE' Makefile ; exec bash\"", // argv[7]
   NULL                        // argv[8] (signals end of pointer array)
   ) ;
@end verbatim

The main command to the 'execlp' function, labelled as 'argv[7]' in the 
above example needs some further clarification.

@itemize @bullet
@item If all we wanted was to invoke the 'grep' command in the new terminal 
window and immediately close the window, then @t{argv[7]} would be the same 
as in the @t{'-p'} option described above:@*
@verb{|   grep -n 'COMPILE' Makefile|}@*
However, what we want to do here is to open the new window, invoke the 
@t{'grep'} command and then leave the window open so the user can view 
the results. The elements of @t{argv[7]} are as follows:
   @itemize @SCIRCLE
   @item @b{@t{bash}}@*
   This is the name of the shell program. It generates a fresh copy 
   of the shell in which to run the 'grep' command.

   @item @b{@t{-c}}@*
   This is the bash @t{"command"} command which indicates that the next 
   token is to be executed by the shell program.

   @item @b{@t{\"}}@*
   This is an @emph{escaped} double-quotation character. This character 
   will be interpreted by the shell program as a quotation mark 
   beginning the command to be executed. If the character were not 
   @t{'escaped'}, then the shell program would discard it, potentially 
   causing the @t{'grep'} utility to mis-interpret any whitespace and 
   @LDQ{}regular expression@RDQ{} characters in the search string.

   @item @b{@t{grep -n 'COMPILE' Makefile}}@*
   This is the 'grep' command sequence. 

   @item @b{@t{;}}@*
   The semicolon character is used to separate a list of commands to 
   be executed sequentially by the shell. In our example, there are 
   two commands, the 'grep' invocation described in the previous line 
   item, and the shell command, 'exec' described in the next item.

   @item @b{@t{exec bash}}@*
   This command @emph{replaces} the currently running copy of @t{'bash'} with 
   a new copy. This may seem odd, but without the 'exec' two copies 
   of the shell would be left running in the window.
   The @emph{effect} of this command is to keep the new window open and 
   to return to the command prompt after all the specified commands 
   have finished.

   @item @b{@t{\"}}@*
   This is another @emph{escaped} double-quotation character, which the
   shell program interprets as the end of the command sequence to be executed.  

   @item @b{@t{NULL}}@*
   This is a null pointer. It signals the end of the @t{argv[]} list.
   @end itemize

Pipes and redirection of output also work within the command sequence:@*
@verb{|   -e "grep -n 'COMPILE' Makefile | grep 'childApp' >./dtmp.txt"|}@*
In this case, the window would close immediately, but our answer is in 
the temp file.

@end itemize
@sp 1

@anchor{Terminal Configuration}
@H5heading{Terminal Configuration - Optional Arguments,
           ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔}
This test accepts optional arguments which are interpreted as configuration 
parameters for launching the child window (or tab within the current window).

@enumerate 1
@item The name of the emulator in which the Salmon application is currently 
running and the name of the shell program have been determined by the 
getEmulator() method. This is referred to as the @LDQ{}parent@RDQ{} window.

@item The configuration of the child window is constructed by the 
DefineChildEmulator() method. This includes the "geometry" for the 
window, consisting of the width, height and position within the screen. 
This configuration can be modified using one or more of the optional 
command-line parameters:

   @enumerate a
   @item If no command line arguments provided, the child window is defined 
   as a small window centered in the screen.
   
   @item The dimensions of the child window may be modified via the first 
   two optional arguments.@*
   Example: @b{@verb{| ./salmon -t 128 25|}}@*
   @t{'128'} is the width of the window in columns, and@*
   @t{'25'}  is the height of the window in rows.@*
   Note that these parameters are not range checked against the size 
   of the computer screen. The author believes that doing such a range 
   check would have added an unnecessary layer of confusion to this 
   simple demonstration app. If these values are not chosen wisely, the 
   invocation of the emulator program may produce unexpected results.

   @item If the first optional parameter is the letter @t{'@b{f}'}, the 
   child window will be opened in full-screen mode, and the geometry 
   parameters will be ignored.@*
   Example: @b{@verb{| ./salmon -t f|}}

   @item If the first optional parameter is the letter @t{'@b{t}'}, 
   then instead of opening a new child window, a new Tab will be 
   opened in the current window.@*
   Example: @b{@verb{| ./salmon -t t|}}@*
   @i{Note: This option does not apply to XTerm, which does not support tabs.}

   @item If the first optional parameter is the letter @t{'@b{h}'} (hint), then 
   display information on using the optional arguments and return without 
   executing the test.@*
   Example: @b{@verb{| ./salmon -t h|}}@*

   @item The third and fourth optional arguments may be used to specify 
   the position of the window within the computer screen. Note, however, 
   that the Wayland compositor will ignore these values for 
   the gnome-terminal. Note also that KDE Konsole has simply given up and 
   no longer supports the @t{'--geometry'} option, and there appears to be 
   no workaround for specification of window offsets.@*
   XTerm still honors the horizontal and vertical offsets specified by 
   the @t{'-geometry'} option. These offsets are specified in pixels.@*
   Example: @b{@verb{| ./salmon -t 128 25 400 200|}}@*
   @t{'128'} is the width of the window in columns@*
   @t{ '25'} is the height of the window in rows@*
   @t{'400'} is the horizontal offset from the left edge of the screen@*
   @t{'200'} is the vertical offset from the top of the screen
   @end enumerate
@end enumerate
@sp 1


@c -------------------------------------------------------------------------------
@anchor{test -D}
@cindex test -D, development
@cindex development, test -D
@cindex standbox
@item @b{@t{-D}} @ @ Sandbox for use during development@*

The @LDQ{}Sandbox@RDQ{} is the play area traditionally reserved for 
exploring new ideas while within a safe, mommy-approved environment.

The @b{@t{Sandbox}} method of the @t{Salmon} application is designed 
to be that safe space for those of us whose mommy is exhausted by our 
constant demands, and who is no longer watching over us every second.

During development, your humble author used this Sandbox extensively 
to fill the knowledge gaps in the standard library documentation for 
the @t{'exec'} group of functions which is somewhere between spartan 
and downright lazy.

@smallquotation
@b{@i{Software Sam must admit that this is among his pet peeves @EMDASH@*
primarily because he spent about half his time in Silicon Valley@*
writing (or rewriting) the documentation for software and hardware@*
projects, both his own and everybody else's. @EMDASH Rant completed!}}
@end smallquotation

For curious experimenters, several of these ad-hoc tests are retained 
as comments in the method header, to provide hints for further development.

@H5heading{Special Tests:,▔▔▔▔▔▔▔▔▔▔▔▔▔▔}

Certain tests have been embedded in the Sandbox code like scarab beetles in 
amber, and may be invoked using the first @emph{optional} argument.@*
Example: @b{@t{./salmon -D dump}}

If optional argument ARG1 == @t{"@b{dump}"}, report emulator/shell information.@*
If optional argument ARG1 == @t{"@b{screen}"}, report dimensions of computer 
screen.
@end itemize
@ifnothtml
@hr90
@end ifnothtml
@sp 2


@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c 03.0 Are You My Mother?:  - - - - - - - - - - - - - - - - - - - - - - - - - -
@c      Gathering information about the terminal - - - - - - - - - - - - - - - -
@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node Are You My Mother?
@unnumbered Are You My Mother?
@cindex 03.0 Are You My Mother?
@cindex process tree
@cindex tree, process
@cindex terminal emulator
@cindex emulator, terminal

@indentedblock
@indentedblock
@ifnothtml
@verbatim
┌──────────────────────────────────────────────────┐
│ This chapter is named in honor of the classic    │
│ children's book of the same name, written and    │
│ illustrated by P.D. Eastman, Random House, 1980. │
└──────────────────────────────────────────────────┘

@end verbatim
@end ifnothtml
@ifhtml
@indentedblock
@CartHtml{This chapter is named in honor of the classic 
children's book of the same name, written and 
illustrated by P.D. Eastman, Random House, 1980.}
@end indentedblock
@end ifhtml
@end indentedblock
@end indentedblock
@sp 1

For any application, knowing the configuration of the host environment is 
critical. Under the X-Windows (X11) windowing system 
@ifhtml
@*
@end ifhtml
@w{(MIT -> X.org Foundation)} there were several tools available for 
query of the system configuration:@*
@verb{| ps|}@*
@verb{| xwininfo|}@*
@verb{| loginctl|}@*
@verb{| xprop|}@*
@verb{| xdpyinfo|}@*
@verb{| xdriinfo|}@*
@verb{| xvinfo|}@*
Under Wayland, these utilities have either disappeared entirely or their 
functionality has been severely limited in the name of @LDQ{}security@RDQ{}.

Much of this system information is still available, but only if you are 
willing to get your hands dirty, like a surgeon playing with the intestines 
of the patient. But like the surgeon in the operating room, caution must be 
used to avoid massive internal bleeding and messages such as: 
@w{@LDQ{}Permission denied@RDQ{}}, @w{@LDQ{}No such file or directory@RDQ{}}, 
@w{@LDQ{}Command not found@RDQ{}}, or our historical favorite: 
@w{@LDQ{}lp0 on fire@RDQ{}} which meant that your Teletype machine was overheating. 
Ahh, those were the days!

In the @t{Salmon} application, we take a few baby steps into this dangerous 
environment by traversing the @t{"process ID tree"} to determine the name 
and version number of the terminal emulator program, as well as the name and 
version number of the currently active shell program.

@H5heading{Terminal Emulators,
           ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔}
The three most popular terminal emulators in the GNU/Linux world are:@*
@verb{|   GNOME Terminal   - 'gnome-terminal'|}@*
@verb{|   KDE Konsole      - 'konsole'|}@*
@verb{|   XWindows XTerm   - 'xterm'|}

Several other branches of the terminal emulator evolution have appeared, 
some as enhancements to the existing functionality, and some as specialized 
tools for specific environments. Some of these are:

@verbatim
tilda          Alacritty   WezTerm        Sakura      xfce4-terminal
terminator     Kitty       Foot           st          urxvt
yakuake        Tilix       LXterminal     PuTTY       rxvt
@end verbatim

While some of these emulators have undeniably interesting capabilities, 
for our current demonstration, we stay with the three most common 
emulators: @t{'gnome-terminal', 'konsole'} and @t{'xterm'}.

@H5heading{Shell Programs,
           ▔▔▔▔▔▔▔▔▔▔▔▔▔▔}
The @LDQ{}shell program@RDQ{} is one of most powerful, yet under-appreciated 
applications in the GNU/Linux world. The @LDQ{}shell@RDQ{} runs within 
any terminal window environment; interpreting user input, launching 
the specified shell utilities and external applications.

As with terminal emulator programs, the choice of a shell program is strongly 
influenced by the host system, the type of work being done on the system and 
personal preferences.

Certain shell programs are installed by default depending on platform and 
configuration. The file “/etc/shells” lists the available shell programs. 
The most common shells seem to be @t{‘sh'} and @t{‘bash’}.

@i{@b{Technical Note:} The @t{'tmux'} program is also listed; however, 
@t{'tmux'} is not an actual shell program. It is a manager program for 
running multiple screens simultaneously. Note also that @t{'sh'} is seldom, 
if ever actually installed on modern systems; instead, @t{'sh'} is generally 
just a symbolic link to @t{'bash'}.}

Other shell programs have small, but wildly enthusiastic user groups.

@verbatim
Z Shell                    - 'zsh'
Friendly Interactive Shell - 'fish'
Korn Shell                 - 'ksh' 
Debian Almquist Shell      - 'dash'
C Shell                    - 'csh'
TENEX Shell                - 'tcsh'
@end verbatim

@LDQ{}Salmon@RDQ{} currently recognizes five shell programs: 
@t{'bash', 'zsh', 'fish', 'ksh'} and @t{'sh'}.


@quotation Note 
It is possible that a valid, but unrecognized terminal emulator@*
or shell program may be encountered. If your favorite emulator/shell@*
are not supported by this application, the code can easily be updated@*
to recognize them. In @t{getEmulator()}, update the two arrays:@*
@t{shNames[], and shVers[]}. Then add a new switch case in@*
@t{DefineChildEmulator()}.
@end quotation

The emulator/shell information is contained in series of temporary files 
located in the system's @t{"@b{/proc}"} (process) directory. The target files 
are identified by the @t{"@b{process ID}" (PID)} of the process being investigated. 

C-library functions are available to identify the @t{process ID} for any 
currently active process.

@verb{|   getpid     - get PID of current process|}@*
@verb{|   getppid    - get PID of parent of current process|}

Once the @t{PID} of the parent process is known, it can be used to identify 
the file containing statistics about that process. For example, if the 
parent @t{PID} is @b{4734}, then the target file will be:@*
@b{@verb{|   /proc/4734/stat|}}@*

This file is a plain text file, so opening as @b{@emph{READ ONLY}} and 
extracting (approximately) the first 128 characters, we get:@*

@verb{|  4734 (bash) S 4663 4734 4734 34818 20813 4194304 6335 |}@*
@verb{|  90409 0 16 7 9 189 47 20 0 1 0 37270 240005120 1569 18|}@*
@verb{|  446744073709551615 |}

The first four(4) tokens contain the information we need:@*
@b{@verb{|  4734 (bash) S 4663|}}@*
These tokens represent, respectively:@*
The PID of the application being run by this process@*
@b{@verb{|  4734|}}@*
The name of the application; in this case, the name of the shell program.@*
@b{@verb{|  (bash)|}}@*
A system identification code (ignored)@*
@b{@verb{|  S|}}@*
This is the gold mine: the @t{PID} for the parent of the application's 
parent process @EMDASH the @LDQ{}grandparent@RDQ{} process, if you will.@*
@b{@verb{|  4663|}}@*

Repeating the process using our newly acquired @t{PID}, we get:@*
@b{@verb{|  4663 (gnome-terminal-) R 1387|}}

We now have the name of the terminal emulator program, and incidentally, 
we also have the name of the shell program which is currently running 
inside the emulator.

The version number of each program can now be requested, and the 
data will be captured to a temporary file:@*
@verb{|  gnome-terminal --version 1>"tempfile_name" 2>/dev/null"|}@*
@verb{|  bash --version 1>"tempfile_name" 2>/dev/null"|}@*

The captured data are then stored in our customized emuData-class 
object, and are then available to the application.
@sp 1

@hr20d{}
@i{@b{Note on climbing the PID Tree:} If a PID of one (1) is encountered, 
@b{@emph{STOP!}} This means that the top of the process tree has been reached.}
@sp 2


@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c 04.0 Building from Source:  - - - - - - - - - - - - - - - - - - - - - - - - -
@c      Compile the application  - - - - - - - - - - - - - - - - - - - - - - - -
@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node Building from Source
@unnumbered Building from Source
@cindex 04.0 Building from Source
@cindex source code

@enumerate 1
@item Open a terminal window of a convenient size.@* 
The application should _build_ in any terminal emulator window; however, 
application functionality testing has been done only in @t{'gnome-terminal'}, 
@t{'konsole'} and @t{'xterm'}.

@item Verify that your compiler is at least version 8.1:@*
@b{@verb{|   g++ --version|}}

@verb{|   g++(GCC) 15.2.1 20260123 (Red Hat 15.2.1-7)|}@*
@verb{|   Copyright (C) 2025 Free Software Foundation, Inc.|}

If you are not using GCC, then verify that your compiler fully supports 
the C++17 standard.

@item Download the Salmon archive and copy it to the directory where your 
software projects live:
@b{@verb{|   cp --preserve=all salmon-x.x.xx.tar.bz2 ~/SoftwareDesign|}}@*
@b{@verb{|   cd ~/SoftwareDesign|}}

@item Unpack the archive.@*
The Salmon directory will be created and all source files will be expanded 
into that directory.@*
@b{@verb{|   tar -xjvf salmon-x.x.xx.tar.bz2|}}

@item Navigate to the source directory:@*
@b{@verb{|   cd Salmon|}}

@item Build both the main application and the target application:@*
@b{@verb{|   gmake all|}}

The Makefile includes additional options if needed:@*
@verb{|gmake         |} build only the @t{'salmon'} application@*
@verb{|gmake child   |} build only the @t{'childApp'} application@*
@verb{|gmake clean   |} remove binaries and object files for clean build

When both applications build without errors and without warnings,@*
@verb{|                |} CONGRATULATIONS!

@item Test the primary application:@*
@b{@verb{|   ./salmon --version|}}

The application version number and copyright information should be displayed.

@format
If the application does not run, then verify that all necessary 
libraries are installed on your system. Run the 'ldd' command to list 
the necessary libraries. The needed libraries should look something 
like the following. These are all standard libraries which should be 
installed on your system by default.

@b{@verb{|ldd epts|}}
@verb{|linux-vdso.so.1 (0x00007f6e7b85a000)|}
@verb{|libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f6e7b400000)|}
@verb{|libm.so.6 => /lib64/libm.so.6 (0x00007f6e7b74a000)|}
@verb{|libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f6e7b71e000)|}
@verb{|libc.so.6 => /lib64/libc.so.6 (0x00007f6e7b20f000)|}
@verb{|/lib64/ld-linux-x86-64.so.2 (0x00007f6e7b85c000)|}
@end format

@item Test communication between parent and child applications:@*
@b{@verb{|   ./salmon -v|}}

You should see something like the following, indicating that both 
applications are functioning properly:

@verbatim
Salmon Swim Upstream To Spawn!
 Invocation: './salmon -v'
 Parent PID: 8592
 calling execv( childApp argv[] )

childApp: PID: 8592
====================
argv[0] childApp
argv[1] -v
argv[2] Types of Salmon:
argv[3] Trout
argv[4] Char
argv[5] Grayling
argv[6] Whitefish

[Salmon]$
@end verbatim
@end enumerate
@spi

@H5heading{Rebuilding the Documentation:,
           ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔}
@enumerate 1
@item Rebuilding the Texinfo documentation requires 'makeinfo' (texi2any) v:6.8 
or greater (v:7.2 recommended).

@item Rebuilding the HTML documentation requires the 'idpp' post-processor 
utility, which is part of the 'Infodoc' package (v:0.0.16) available 
for download on the author's website.@*
If @t{'idpp'} is not found on the path, CSS formatting will not be applied 
to the HTML document; however, both the @t{'.info'} and @t{'.html'} 
documents will have been built correctly. (The HTML document will just 
look ugly.)

@item Downloand and expand the archive as described above.

@item Navigate to the documentation directory:@*
@b{@verb{|   cd Salmon/Texinfo|}}

@item Build both the @t{'.info'} and @t{.html} versions of the document, 
and apply CSS formatting to the HTML document:@*
@b{@verb{|   gmake|}}

@item To verify the build:
   @enumerate a
   @item Invoke the @t{'info'} reader:@*
   @b{@verb{|   info -f salmon.info|}}
   @item Then, open @t{'salmon.html'} in your favorite browser.
   @end enumerate
@end enumerate
@sp 2


@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c 05.0 gString Text Tool: - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c      Text Internationalization and formatting tool  - - - - - - - - - - - - -
@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c gString Text Tool:  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c This definition disables external xrefs in the gString chapter.
@c External xrefs are used only when the chapter is integrated 
@c into the NcDialogAPI documentation.
@set GSTRING_STANDALONE
@c gString class Chapter Index number macro.
@c Because gString and gString documentation is included in several 
@c different packages, this macro allows chapter indexing.
@macro GSChIndx{x}
@cindex 05.\x\
@end macro
@include gStringTextTool.texi


@sp 2


@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c 06.0 Technical Support: - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c      Make suggestions, report problems  - - - - - - - - - - - - - - - - -
@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node Technical Support
@unnumbered Technical Support
@cindex 06.0 Technical Support
@cindex technical support
@cindex support, technical

@display
Please Note: All trademarks and service marks mentioned in this
document are the entirely-too-proprietary property of their
respective owners, and this author makes no representation of
affiliation with or ownership of any of the damned things.
@end display

@cindex contact info
@section Contact

@display
Salmon (salmon) binary, source code and associated Texinfo 
documentation were written and are maintained by:

                         Mahlon R. Smith,
                      The Software Samurai
                 Beijing University of Technology
                 on the web at: @SAMADDRESS 

For bugs, suggestions, periodic updates, or possible praise, 
please post a message to the author via website.

The author wishes to thank everyone for their intelligent, kind
and thoughtful responses.  (ranters I can live without)
@end display

@ifnothtml
@hr40{}
@end ifnothtml
@ifhtml
@html
<div style="margin-left:4%; margin-right:46%;"><hr></div>
@end html
@end ifhtml

@cindex by the same author
@anchor{by the same author}
@section By the same author

@include same_author.texi

@sp 2


@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c 07.0 Copyright Notice:  - - - - - - - - - - - - - - - - - - - - - - - - - - -
@c      Boring, but useful   - - - - - - - - - - - - - - - - - - - - - - - - - -
@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node Copyright Notice
@unnumbered Copyright Notice
@cindex 07.0 Copyright Notice

@format
The Salmon binary and source code are released under
the GNU General Public License (GPL 3+), and
the user documentation (this document) is released under
the GNU Free Documentation License (FDL 1.3+):
@end format
@sp 1

@insertcopying

@menu
* GNU General Public License::
* GNU Free Documentation License::
@end menu


@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@lowersections
@node GNU General Public License
@unnumbered GNU General Public License
@cindex 07.1 GNU General Public License

@include gpl-3.0.texi

@node GNU Free Documentation License
@unnumbered GNU Free Documentation License
@cindex 07.2 GNU Free Documentation License

@include fdl-1.3.texi

@raisesections

@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node Index
@unnumbered Index

@printindex cp

@bye
