библиотека программных диалогов с интерактивными программами (programmed dialogue library with interactive programs)
EXPECT PROCESSING
While it is possible to use read() to read information from a
process spawned by exp_spawnl
or exp_spawnv
, more convenient
functions are provided. They are as follows:
int
exp_expectl(fd,type1,pattern1,[re1,],value1,type2,...,exp_end);
int fd;
enum exp_type type;
char *pattern1, *pattern2, ...;
regexp *re1, *re2, ...;
int value1, value2, ...;
int
exp_fexpectl(fp,type1,pattern1,[re1,]value1,type2,...,exp_end);
FILE *fp;
enum exp_type type;
char *pattern1, *pattern2, ...;
regexp *re1, *re2, ...;
int value1, value2, ...;
enum exp_type {
exp_end,
exp_glob,
exp_exact,
exp_regexp,
exp_compiled,
exp_null,
};
struct exp_case {
char *pattern;
regexp *re;
enum exp_type type;
int value;
};
int
exp_expectv(fd,cases);
int fd;
struct exp_case *cases;
int
exp_fexpectv(fp,cases);
FILE *fp;
struct exp_case *cases;
extern int exp_timeout;
extern char *exp_match;
extern char *exp_match_end;
extern char *exp_buffer;
extern char *exp_buffer_end;
extern int exp_match_max;
extern int exp_full_buffer;
extern int exp_remove_nulls;
The functions wait until the output from a process matches one of
the patterns, a specified time period has passed, or an EOF is
seen.
The first argument to each function is either a file descriptor
or a stream. Successive sets of arguments describe patterns and
associated integer values to return when the pattern matches.
The type argument is one of four values. exp_end indicates that
no more patterns appear. exp_glob indicates that the pattern is
a glob-style string pattern. exp_exact indicates that the
pattern is an exact string. exp_regexp indicates that the
pattern is a regexp-style string pattern. exp_compiled indicates
that the pattern is a regexp-style string pattern, and that its
compiled form is also provided. exp_null indicates that the
pattern is a null (for debugging purposes, a string pattern must
also follow).
If the compiled form is not provided with the functions
exp_expectl
and exp_fexpectl
, any pattern compilation done
internally is thrown away after the function returns. The
functions exp_expectv
and exp_fexpectv
will automatically compile
patterns and will not throw them away. Instead, they must be
discarded by the user, by calling free on each pattern. It is
only necessary to discard them, the last time the cases are used.
Regexp subpatterns matched are stored in the compiled regexp.
Assuming "re" contains a compiled regexp, the matched string can
be found in re->startp[0]. The match substrings (according to
the parentheses) in the original pattern can be found in
re->startp[1], re->startp[2], and so on, up to re->startp[9].
The corresponding strings ends are re->endp[x] where x is that
same index as for the string start.
The type exp_null matches if a null appears in the input. The
variable exp_remove_nulls must be set to 0 to prevent nulls from
being automatically stripped. By default, exp_remove_nulls is
set to 1 and nulls are automatically stripped.
exp_expectv
and exp_fexpectv
are useful when the number of
patterns is not known in advance. In this case, the sets are
provided in an array. The end of the array is denoted by a
struct exp_case with type exp_end. For the rest of this
discussion, these functions will be referred to generically as
expect.
If a pattern matches, then the corresponding integer value is
returned. Values need not be unique, however they should be
positive to avoid being mistaken for EXP_EOF, EXP_TIMEOUT, or
EXP_FULLBUFFER. Upon EOF or timeout, the value EXP_EOF
or
EXP_TIMEOUT
is returned. The default timeout period is 10
seconds but may be changed by setting the variable exp_timeout
.
A value of -1 disables a timeout from occurring. A value of 0
causes the expect function to return immediately (i.e., poll)
after one read(). However it must be preceded by a function such
as select, poll, or an event manager callback to guarantee that
there is data to be read.
If the variable exp_full_buffer is 1, then EXP_FULLBUFFER is
returned if exp_buffer fills with no pattern having matched.
When the expect function returns, exp_buffer
points to the buffer
of characters that was being considered for matching.
exp_buffer_end
points to one past the last character in
exp_buffer. If a match occurred, exp_match
points into
exp_buffer
where the match began. exp_match_end
points to one
character past where the match ended.
Each time new input arrives, it is compared to each pattern in
the order they are listed. Thus, you may test for absence of a
match by making the last pattern something guaranteed to appear,
such as a prompt. In situations where there is no prompt, you
must check for EXP_TIMEOUT
(just like you would if you were
interacting manually). More philosophy and strategies on
specifying expect
patterns can be found in the documentation on
the expect
program itself. See SEE ALSO below.
Patterns are the usual C-shell-style regular expressions. For
example, the following fragment looks for a successful login,
such as from a telnet dialogue.
switch (exp_expectl(
exp_glob,"connected",CONN,
exp_glob,"busy",BUSY,
exp_glob,"failed",ABORT,
exp_glob,"invalid password",ABORT,
exp_end)) {
case CONN: /* logged in successfully */
break;
case BUSY: /* couldn't log in at the moment */
break;
case EXP_TIMEOUT:
case ABORT: /* can't log in at any moment! */
break;
default: /* problem with expect */
}
Asterisks (as in the example above) are a useful shorthand for
omitting line-termination characters and other detail. Patterns
must match the entire output of the current process (since the
previous read on the descriptor or stream). More than 2000 bytes
of output can force earlier bytes to be "forgotten". This may be
changed by setting the variable exp_match_max
. Note that
excessively large values can slow down the pattern matcher.