Optional command-line arguments ‘ARG1’ through ‘ARG4’
These optional comand-line arguments are recognized by the
‘–v’,
‘–l’
and
‘–f’ options, and specified arguments will be passed to the child application
(‘childApp’) which will display them to verify that they were passed successfully.
./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!
- –v execv() function
Pass an argv[] array to childApp (calling application terminates).
The ‘v’ in “execv” indicates the argv[] vector array, and as a software
designer, you may be aware that this is an array of char pointers char const* argv[]
with the last pointer in the array being the NULL pointer.
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
}
execv ( fileName, argV ) ;
- –l execl() function
Pass a list of individual arguments to childApp (calling application terminates).
The ‘l’ in “execl” indicates a list (sequence) of individual arguments, with
the last item in the list being the NULL pointer.
Example:
const char* fileName = "./childApp" ;
execl ( fileName, // path/filename of target application
&filename[2], // this should be the 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
) ;
- –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 files to search.
grep -n 'COMPILE' Makefile MakeChild
Example:
execlp ( "grep", "grep", "-n", "COMPILE", "Makefile", "MakeChild", NULL ) ;
Note that each argument to execlp() is a separate string.
- –f execl() function executed by “forked” process.
The primary process calls the “fork” (actually “vfork”) function to create a child
process, then the child process invokes an external program (childApp) which produces some output, then exits.
After calling “vfork”, the parent process waits silently for the child process to terminate,
at which time it reclaims control of the I/O streams.
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
}
}
- –s execvp() function executed by “forked” process.
The primary process calls the “fork” (actually “vfork”) function to create a child
process, then the child process invokes an external program (childApp) which produces some output, then exits.
After calling “vfork”, the parent process continues execution immediately.
For this example, the output streams (‘stdout’ and ‘stderr’) of the child process are
redirected to temporary files ‘stdout.txt’ and ‘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.
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 ;
}
}
After both programs have terminated, the output which was redirected to the temporary files may be
viewed using the command:
cat *.txt
- –t execl() function executed by “forked” process.
The primary process calls the “fork” (actually “vfork”) function to create a child
process, then the child process opens a new terminal window and invokes an external program (grep) within
the new window.
After calling “vfork”, the parent process continues execution immediately.
In the Salmon source code, we perform some magic to:
- determine the name of the terminal emulator program which is currently running,
- determine the name of the shell program running in the terminal window,
- calculate the size and position for the new terminal window.
However, the following example has been simplified for clarity. In the example, we assume the GNOME terminal emulator,
the “bash” shell program and convenient constants for the size and position for the window.
Example:
execlp ( gnome-terminal, // name of terminal program
"gnome-terminal", // argv[0] (bare program name)
"--geometry=65x9+400+300", // argv[1] (size and position for new window)
"--hide-menubar", // argv[2] (disable the window's menu bar)
"--window", // argv[3] (specify new window rather than default tab)
"-q", // argv[4] (no output to parent window)
"-e", // argv[5] (the execlp 'execute' command)
// argv[6] (a complex command to be executed in the new terminal window)
"bash -c \"grep -n \'COMPILE\' Makefile MakeChild ; exec bash\"",
NULL
) ;
The main command to the ‘execlp’ function, labelled as argv[6] in the above example needs some
further clarification.
Salmon/ // Source code directory
Salmon.cpp // Main demonstration application
childApp.cpp // Secondary application invoked by the child process
GlobalDef.hpp // '#include' files and general definitions
Makefile // Build the 'salmon' application
MakeChild // Build the 'childApp' application
README // Package description, release notes