Add a man page.
[miniexpect.git] / miniexpect.pod
1 =encoding utf8
2
3 =head1 NAME
4
5 miniexpect - A very simple expect library for C.
6
7 =head1 SYNOPSIS
8
9  #include <errno.h>
10  #include <sys/wait.h>
11  #include <pcre.h>
12  #include <miniexpect.h>
13  
14  mexp_h *h;
15  h = mexp_spawnl ("ssh", "ssh", "host");
16  switch (mexp_expect (h, regexps, ovector, ovecsize)) {
17    ...
18  }
19  mexp_close (h);
20
21  cc prog.c -o prog -lminiexpect
22
23 =head1 DESCRIPTION
24
25 miniexpect is a very simple expect-like library for C.
26
27 It has a saner interface than libexpect, and doesn't depend on Tcl.
28 It is also thread safe, const-correct and uses modern C standards.
29
30 It is standalone, except that it requires the PCRE (Perl Compatible
31 Regular Expressions) library from http://www.pcre.org/.  The PCRE
32 dependency is fundamental because we want to offer the most powerful
33 regular expression syntax to match on, but more importantly because
34 PCRE has a convenient way to detect partial matches which made this
35 library very simple to implement.
36
37 This manual page documents the API.  Examples of how to use the API
38 can be found in the source directory.
39
40 =head1 CONCEPTS
41
42 Miniexpect lets you start up an external program, control it (by
43 sending commands to it), and close it down gracefully.  Two things
44 make this different from other APIs like L<popen(3)> and L<system(3)>:
45 Firstly miniexpect creates a pseudoterminal (pty).  Secondly
46 miniexpect lets you match the output of the program using regular
47 expressions.  Both of these are handy for controlling interactive
48 programs that might (for example) ask for passwords, but you can use
49 miniexpect on just about any external program.
50
51 You can control multiple programs at the same time.
52
53 =head1 SPAWNING THE SUBPROCESS
54
55 There are two calls for creating a subprocess:
56
57 B<mexp_h *mexp_spawnl (const char *file, const char *arg, ...);>
58
59 This creates a subprocess running the external program C<file> (the
60 current C<$PATH> is searched unless you give an absolute path).
61 C<arg, ...> are the arguments to the program.  Usually the first
62 argument should be the name of the program.
63
64 The return value is a handle (see next section).
65
66 If there was an error running the subprocess, C<NULL> is returned and
67 the error is available in C<errno>.
68
69 For example, to run an ssh subprocess you could do:
70
71  h = mexp_spawnl ("ssh", "ssh", "-l", "root", "host");
72
73 or to run a particular ssh binary:
74
75  h = mexp_spawnl ("/usr/local/bin/ssh", "ssh", "-l", "root", "host");
76
77 An alternative to C<mexp_spawnl> is:
78
79 B<mexp_h *mexp_spawnv (const char *file, char **argv);>
80
81 This is the same as C<mexp_spawnl> except that you pass the arguments
82 in a NULL-terminated array.
83
84 =head1 HANDLES
85
86 After spawning a subprocess, you get back a handle.  There are various
87 fields in this handle which you can read or write:
88
89  struct mexp_h {
90    int fd;
91    pid_t pid;
92
93 C<fd> is the pty of the subprocess.  You can read and write to this if
94 you want, although convenience functions are also provided (see
95 below).  C<pid> is the process ID of the subprocess.  You can send it
96 signals if you want.
97
98    int timeout;
99
100 C<timeout> is the timeout in milliseconds (1/1000th of a second) used
101 by C<mexp_expect> (see below).  You can set this before calling
102 C<mexp_expect> if you want.  Setting it to -1 means no timeout.  The
103 default setting is 60000 (60 seconds).
104
105    char *buffer;
106    size_t len;
107    size_t alloc;
108
109 If C<mexp_expect> returns a match then these variables contain the
110 read buffer.  Note this buffer does not contain the full input from
111 the process, but it will contain at least the part matched by the
112 regular expression (and maybe some more).  C<buffer> is the read
113 buffer and C<len> is the number of bytes of data in the buffer.
114
115    size_t read_size;
116
117 Callers may set this to the natural size (in bytes) for reads from the
118 subprocess.  The default is 1024.  Most callers will not need to
119 change this.
120
121    int pcre_error;
122
123 If C<mexp_expect> returns C<MEXP_PCRE_ERROR>, then the actual PCRE
124 error code returned by L<pcre_exec(3)> is available here.  For a list
125 of PCRE error codes, see L<pcreapi(3)>.
126
127    void *user1;
128    void *user2;
129    void *user3;
130
131 Opaque pointers for use by the caller.  The library will not touch
132 these.
133
134  };
135  
136  typedef struct mexp_h mexp_h;
137
138 =head1 CLOSING THE HANDLE
139
140 To close the handle and clean up the subprocess, call:
141
142 B<int mexp_close (mexp_h *h);>
143
144 This returns the status code from the subprocess.  This is in the form
145 of a L<waitpid(2)>/L<system(3)> status so you have to use the macros
146 C<WIFEXITED>, C<WEXITSTATUS>, C<WIFSIGNALED>, C<WTERMSIG> etc defined
147 in C<E<lt>sys/wait.hE<gt>> to parse it.
148
149 If there was a system call error, then C<-1> is returned.  The error
150 will be in C<errno>.
151
152 Notes:
153
154 =over 4
155
156 =item *
157
158 Even in error cases, the handle is always closed and its memory is
159 freed by this call.
160
161 =item *
162
163 It is normal for the kernel to send SIGHUP to the subprocess.
164
165 If the subprocess doesn't catch the SIGHUP, then it will die
166 with status:
167
168  WIFSIGNALED (status) && WTERMSIG (status) == SIGHUP
169
170 This case should not necessarily be considered an error.
171
172 =back
173
174 =head1 EXPECT FUNCTION
175
176 Miniexpect contains a powerful regular expression matching function
177 based on L<pcre(3)>:
178
179 B<int mexp_expect (mexp_h *h, const mexp_regexp *regexps,
180 int *ovector, int ovecsize);>
181
182 The output of the subprocess is matched against the list of PCRE
183 regular expressions in C<regexps>.  C<regexps> is a list of regular
184 expression structures:
185
186  struct mexp_regexp {
187    int r;
188    const pcre *re;
189    const pcre_extra *extra;
190    int options;
191  };
192  typedef struct mexp_regexp mexp_regexp;
193
194 C<r> is the integer code returned from C<mexp_expect> if this regular
195 expression matches.  It B<must> be E<gt> 0.  C<r == 0> indicates the
196 end of the list of regular expressions.  C<re> is the compiled regular
197 expression.
198
199 Possible return values are:
200
201 =over 4
202
203 =item C<MEXP_TIMEOUT>
204
205 No input matched before the timeout (C<h-E<gt>timeout>) was
206 reached.
207
208 =item C<MEXP_EOF>
209
210 The subprocess closed the connection.
211
212 =item C<MEXP_ERROR>
213
214 There was a system call error (eg. from the read call).  The error is
215 returned in C<errno>.
216
217 =item C<MEXP_PCRE_ERROR>
218
219 There was a C<pcre_exec> error.  C<h-E<gt>pcre_error> is set to the
220 error code.  See L<pcreapi(3)> for a list of the C<PCRE_*> error codes
221 and what they mean.
222
223 =item C<r> E<gt> 0
224
225 If any regexp matches, the associated integer code (C<regexps[].r>)
226 is returned.
227
228 =back
229
230 Notes:
231
232 =over 4
233
234 =item *
235
236 C<regexps> may be NULL or an empty list, which means we don't match
237 against a regular expression.  This is useful if you just want to wait
238 for EOF or timeout.
239
240 =item *
241
242 C<regexps[].re>, C<regexps[].extra>, C<regexps[].options>, C<ovector>
243 and C<ovecsize> are passed through to the L<pcre_exec(3)> function.
244
245 =back
246
247 =head2 mexp_expect example
248
249 It is easier to understand C<mexp_expect> by considering a simple
250 example.
251
252 In this example we are waiting for ssh to either send us a password
253 prompt, or (if no password was required) a command prompt, and based
254 on the output we will either send back a password or a command.
255
256 The unusual C<(mexp_regexp[]){...}> syntax is called a "compound
257 literal" and is available in C99.  If you need to use an older
258 compiler, you can just use a local variable instead.
259
260  mexp_h *h;
261  char *errptr;
262  int offset;
263  pcre *password_re, *prompt_re;
264  int ovecsize = 12;
265  int ovector[ovecsize];
266  
267  password_re = pcre_compile ("assword", 0, &errptr, &offset, NULL);
268  prompt_re = pcre_compile ("[$#] ", 0, &errptr, &offset, NULL);
269  
270  switch (mexp_expect (h,
271                       (mexp_regexp[]) {
272                         { 100, .re = password_re },
273                         { 101, .re = prompt_re },
274                         { 0 },
275                       }, ovector, ovecsize)) {
276   case 100:
277     /* here you would send a password */
278     break;
279   case 101:
280     /* here you would send a command */
281     break;
282   case MEXP_EOF:
283     fprintf (stderr, "error: ssh closed the connection unexpectedly\n");
284     exit (EXIT_FAILURE);
285   case MEXP_TIMEOUT:
286     fprintf (stderr, "error: timeout before reaching the prompt\n");
287     exit (EXIT_FAILURE);
288   case MEXP_ERROR:
289     perror ("mexp_expect");
290     exit (EXIT_FAILURE);
291   case MEXP_PCRE_ERROR:
292     fprintf (stderr, "error: PCRE error: %d\n", h->pcre_error);
293     exit (EXIT_FAILURE);
294  }
295
296 =head1 SENDING COMMANDS TO THE SUBPROCESS
297
298 You can write to the subprocess simply by writing to C<h-E<gt>fd>.
299 However we also provide a convenience function:
300
301 B<int mexp_printf (mexp_h *h, const char *fs, ...);>
302
303 This returns the number of bytes, if the whole message was written OK.
304 If there was an error, -1 is returned and the error is available in
305 C<errno>.  Note that this function will not do a partial write.  If it
306 cannot write all the data, then it will return an error.
307
308 =head1 SOURCE
309
310 Source is available from:
311 L<http://git.annexia.org/?p=miniexpect.git;a=summary>
312
313 =head1 SEE ALSO
314
315 L<pcre(3)>,
316 L<pcre_exec(3)>,
317 L<pcreapi(3)>,
318 L<waitpid(2)>,
319 L<system(3)>.
320
321 =head1 AUTHORS
322
323 Richard W.M. Jones (C<rjones at redhat dot com>)
324
325 =head1 LICENSE
326
327 The library is released under the Library GPL (LGPL) version 2 or at
328 your option any later version.
329
330 =head1 COPYRIGHT
331
332 Copyright (C) 2014 Red Hat Inc.