sho - Execute programs from a shell in a pseudo terminal programmatically.
#include <mba/shellout.h>
SHO_FLAGS_INTERACT
SHO_FLAGS_ISATTY
struct sho {
char ps1[32];
int flags;
pid_t pid;
int ptym;
struct termios t0;
};
struct sho *sho_open(const char *sh, const char *ps1, int flags);
int sho_close(struct sho *sh);
int sho_expect(struct sho *sh, const char *pv[], int pn, char *dst, size_t dn, int timeout);
int sho_loop(struct sho *sh, const char *pv[], int pn, int timeout);
The shellout(3m) module provides a robust interface to a UNIX shell such
as sh or bash. Spawned programs may be controlled interactively from a
terminal (i.e. "shell out") or entirely in the background (i.e.
cron, network daemon, etc). For most purposes this functionality is identical
to that of the popular expect(1) program.
The svcond(3m) module is not available in the Win32
environment. This module also does not work on HP-UX because it does not
support the forkpty(3) function.
- open
- The sho_open function uses forkpty(3) and execvp(3)
to execute a UNIX shell in a pseudo terminial. The struct sho *
object returned may be used with sho_expect, writen, etc to
interact with the shell. Writing characters to the sh->ptym (PTY
master) descriptor will be read by the shell as if they had been typed at
a terminal. A struct sho * must be closed with
sho_close.
- close
- The sho_close function calls wait(2) to wait for the shell
process to exit. The shell will not exit until it is instructed to. This
can be occomplished by writing "exit $?\n" or if the program
spawned within the shell is taking too long, a Ctrl-C may be written by
sending "\x03\n". Or, as a last resort, SIGKILL may be
sent to sh->pid with kill(2).
- expect
- The sho_expect function accepts a "pattern vector" of
pn strings to match and reads characters from the shell represented
by sh copying each into dst for no more than dn bytes
and returns either;
the index of the matching pattern + 1,
zero if EOF was read from sh->ptym,
or -1 if timeout was exceeded or another error occured.
Tips: It is very easy to be confused about what you think the
shell is doing and what it is really doing. It is important to emulate
what happens when you type the equivalent input in a shell in a terminal
window but consider that the shell does not echo your commands. The
shell will just write the output of the program followed by the shell
prompt (whatever you defined that to be). If you are issueing multiple
commands or the "exit $?\n" command take care not to write the
commands before the shell is ready (receive the shell prompt). Finally,
the buffer passed to sho_expect will only contain the characters
up to and including the pattern that matched. If the pattern matched is
not the shell prompt it will be necessary to call sho_expect
again to match the prompt before another command may be issued.
- loop
- The sho_loop function uses the select(2) system call to read
from the shell and write to stdout at the same time. The loop will
exit when either one of pn patterns at the beginning of the pattern
vector pv is encountered or the timeout period has expired.
When combined with the SHO_FLAGS_INTERACT flag passed
to sho_open this will effectively create a shell within a shell.
Note, currently some programs will not operate correctly (e.g. vi)
because certain termios flags are not optimal for interactive
sessions. This would need futher study.
- open
- The sho_open function returns the new shell instance or NULL if an
error occured in which case errno will be set appropriately.
- close
- The sho_close function returns the exit status of the shell.
However, normally it is desireable to return the exit status of the last
program to run within that shell. In this case the special shell variable
"$?" which evaluates to the exit status of the last program to
run may passed to the exit command such as "exit $?\n".
- expect
- The sho_expect function returns the index of the matching pattern +
1, 0 if EOF was read, or -1 if an error occured in which case errno will
be set appropriately. If the timeout period is exceeded
sho_expect will return -1 and set errno to EINTR.
- loop
- The sho_loop function returns the index of the matching pattern +
1, 0 if EOF was read, or -1 if an error occured in which case errno will
be set appropriately. If the timeout period is exceeded
sho_expect will return -1 and set errno to EINTR.