tests: add "missing" initializers
[miniexpect.git] / miniexpect.pod
index 827a268..7453859 100644 (file)
@@ -2,23 +2,24 @@
 
 =head1 NAME
 
 
 =head1 NAME
 
-miniexpect - A very simple expect library for C.
+miniexpect - A very simple expect library
 
 =head1 SYNOPSIS
 
  #include <errno.h>
  #include <sys/wait.h>
 
 =head1 SYNOPSIS
 
  #include <errno.h>
  #include <sys/wait.h>
- #include <pcre.h>
+ #define PCRE2_CODE_UNIT_WIDTH 8
+ #include <pcre2.h>
  #include <miniexpect.h>
  
  mexp_h *h;
  #include <miniexpect.h>
  
  mexp_h *h;
- h = mexp_spawnl ("ssh", "ssh", "host");
- switch (mexp_expect (h, regexps, ovector, ovecsize)) {
+ h = mexp_spawnl ("ssh", "ssh", "host", NULL);
+ switch (mexp_expect (h, regexps, match_data)) {
    ...
  }
  mexp_close (h);
 
    ...
  }
  mexp_close (h);
 
- cc prog.c -o prog -lminiexpect -lpcre
+ cc prog.c -o prog -lminiexpect -lpcre2-8
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
@@ -30,10 +31,10 @@ Tcl.  It is also thread safe, const-correct and uses modern C
 standards.
 
 Miniexpect is a standalone library, except for a single dependency: it
 standards.
 
 Miniexpect is a standalone library, except for a single dependency: it
-requires the PCRE (Perl Compatible Regular Expressions) library from
-L<http://www.pcre.org/>.  The PCRE dependency is fundamental because
+requires the PCRE2 (Perl Compatible Regular Expressions) library from
+L<http://www.pcre.org/>.  The PCRE2 dependency is fundamental because
 we want to offer the most powerful regular expression syntax to match
 we want to offer the most powerful regular expression syntax to match
-on, but more importantly because PCRE has a convenient way to detect
+on, but more importantly because PCRE2 has a convenient way to detect
 partial matches which made this library very simple to implement.
 
 This manual page documents the API.  Examples of how to use the API
 partial matches which made this library very simple to implement.
 
 This manual page documents the API.  Examples of how to use the API
@@ -54,14 +55,15 @@ You can control multiple programs at the same time.
 
 =head1 SPAWNING THE SUBPROCESS
 
 
 =head1 SPAWNING THE SUBPROCESS
 
-There are two calls for creating a subprocess:
+There are four calls for creating a subprocess:
 
 B<mexp_h *mexp_spawnl (const char *file, const char *arg, ...);>
 
 This creates a subprocess running the external program C<file> (the
 current C<$PATH> is searched unless you give an absolute path).
 
 B<mexp_h *mexp_spawnl (const char *file, const char *arg, ...);>
 
 This creates a subprocess running the external program C<file> (the
 current C<$PATH> is searched unless you give an absolute path).
-C<arg, ...> are the arguments to the program.  Usually the first
-argument should be the name of the program.
+C<arg, ...> are the arguments to the program.  You should terminate
+the list of arguments with C<NULL>.  Usually the first argument should
+be the name of the program.
 
 The return value is a handle (see next section).
 
 
 The return value is a handle (see next section).
 
@@ -70,11 +72,11 @@ the error is available in C<errno>.
 
 For example, to run an ssh subprocess you could do:
 
 
 For example, to run an ssh subprocess you could do:
 
- h = mexp_spawnl ("ssh", "ssh", "-l", "root", "host");
+ h = mexp_spawnl ("ssh", "ssh", "-l", "root", "host", NULL);
 
 or to run a particular ssh binary:
 
 
 or to run a particular ssh binary:
 
- h = mexp_spawnl ("/usr/local/bin/ssh", "ssh", "-l", "root", "host");
+ h = mexp_spawnl ("/usr/local/bin/ssh", "ssh", "-l", "root", "host", NULL);
 
 An alternative to C<mexp_spawnl> is:
 
 
 An alternative to C<mexp_spawnl> is:
 
@@ -83,30 +85,99 @@ B<mexp_h *mexp_spawnv (const char *file, char **argv);>
 This is the same as C<mexp_spawnl> except that you pass the arguments
 in a NULL-terminated array.
 
 This is the same as C<mexp_spawnl> except that you pass the arguments
 in a NULL-terminated array.
 
+There are also two versions of the above calls which take flags:
+
+B<mexp_h *mexp_spawnlf (unsigned flags, const char *file, const char *arg, ...);>
+
+B<mexp_h *mexp_spawnvf (unsigned flags, const char *file, char **argv);>
+
+The flags may contain the following values, logically ORed together:
+
+=over 4
+
+=item B<MEXP_SPAWN_KEEP_SIGNALS>
+
+Do not reset signal handlers to C<SIG_DFL> in the subprocess.
+
+=item B<MEXP_SPAWN_KEEP_FDS>
+
+Do not close file descriptors E<ge> 3 in the subprocess.
+
+=item B<MEXP_SPAWN_COOKED_MODE> or B<MEXP_SPAWN_RAW_MODE>
+
+Configure the pty in cooked mode or raw mode.  Raw mode is the
+default.
+
+=back
+
 =head1 HANDLES
 
 =head1 HANDLES
 
-After spawning a subprocess, you get back a handle.  There are various
-fields in this handle which you can read or write:
+After spawning a subprocess, you get back a handle which is a pointer
+to a struct:
+
+ struct mexp_h;
+ typedef struct mexp_h mexp_h;
+
+Various methods can be used on the handle:
+
+B<int mexp_get_fd (mexp_h *h);>
+
+Return the file descriptor of the pty of the subprocess.  You can read
+and write to this if you want, although convenience functions are also
+provided (see below).
+
+B<pid_t mexp_get_pid (mexp_h *h);>
+
+Return the process ID of the subprocess.  You can send it signals if
+you want.
+
+B<int mexp_get_timeout_ms (mexp_h *h);>
+
+B<void mexp_set_timeout_ms (mexp_h *h, int millisecs);>
+
+B<void mexp_set_timeout (mexp_h *h, int secs);>
+
+Get or set the timeout used by C<mexp_expect> [see below].  The
+resolution is milliseconds (1/1000th of a second).  Set this before
+calling C<mexp_expect>.  Passing -1 to either of the C<set_> methods
+means no timeout.  The default setting is 60000 milliseconds (60
+seconds).
 
 
- struct mexp_h {
-   int fd;
-   pid_t pid;
+B<size_t mexp_get_read_size (mexp *h);>
 
 
-C<fd> is the pty of the subprocess.  You can read and write to this if
-you want, although convenience functions are also provided (see
-below).  C<pid> is the process ID of the subprocess.  You can send it
-signals if you want.
+B<void mexp_set_read_size (mexp *h, size_t read_size);>
 
 
-   int timeout;
+Get or set the natural size (in bytes) for reads from the subprocess.
+The default is 1024.  Most callers will not need to change this.
 
 
-C<timeout> is the timeout in milliseconds (1/1000th of a second) used
-by C<mexp_expect> (see below).  You can set this before calling
-C<mexp_expect> if you want.  Setting it to -1 means no timeout.  The
-default setting is 60000 (60 seconds).
+B<int mexp_get_pcre_error (mexp *h);>
 
 
-   char *buffer;
-   size_t len;
-   size_t alloc;
+When C<mexp_expect> [see below] calls the PCRE function
+L<pcre2_match(3)>, it stashes the return value in the C<pcre_error>
+field in the handle, and that field is returned by this method.
+
+If C<mexp_expect> returns C<MEXP_PCRE_ERROR>, then the actual PCRE
+error code returned by L<pcre2_match(3)> is available by calling this
+method.  For a list of PCRE error codes, see L<pcre2api(3)>.
+
+B<void mexp_set_debug_file (mexp *h, FILE *fp);>
+
+B<FILE *mexp_get_debug_file (mexp *h);>
+
+Set or get the debug file of the handle.  To enable debugging, pass a
+non-C<NULL> file handle, eg. C<stderr>.  To disable debugging, pass
+C<NULL>.  Debugging messages are printed on the file handle.
+
+Note that all output and input gets printed, including passwords.  To
+prevent passwords from being printed, modify your code to call
+C<mexp_printf_password> instead of C<mexp_printf>.
+
+The following fields in the handle do not have methods, but can be
+accessed directly instead:
+
+ char *buffer;
+ size_t len;
+ size_t alloc;
 
 If C<mexp_expect> returns a match then these variables contain the
 read buffer.  Note this buffer does not contain the full input from
 
 If C<mexp_expect> returns a match then these variables contain the
 read buffer.  Note this buffer does not contain the full input from
@@ -114,7 +185,7 @@ the process, but it will contain at least the part matched by the
 regular expression (and maybe some more).  C<buffer> is the read
 buffer and C<len> is the number of bytes of data in the buffer.
 
 regular expression (and maybe some more).  C<buffer> is the read
 buffer and C<len> is the number of bytes of data in the buffer.
 
  ssize_t next_match;
+ ssize_t next_match;
 
 If C<mexp_expect> returns a match, then C<next_match> points to the
 first byte in the buffer I<after> the fully matched expression.  (It
 
 If C<mexp_expect> returns a match, then C<next_match> points to the
 first byte in the buffer I<after> the fully matched expression.  (It
@@ -127,29 +198,13 @@ C<-1> in order to ignore the remainder of the buffer.  In most cases
 callers can ignore this field, and C<mexp_expect> will just do the
 right thing when called repeatedly.
 
 callers can ignore this field, and C<mexp_expect> will just do the
 right thing when called repeatedly.
 
-   size_t read_size;
-
-Callers may set this to the natural size (in bytes) for reads from the
-subprocess.  The default is 1024.  Most callers will not need to
-change this.
-
-   int pcre_error;
-
-If C<mexp_expect> returns C<MEXP_PCRE_ERROR>, then the actual PCRE
-error code returned by L<pcre_exec(3)> is available here.  For a list
-of PCRE error codes, see L<pcreapi(3)>.
-
-   void *user1;
-   void *user2;
-   void *user3;
+ void *user1;
+ void *user2;
+ void *user3;
 
 Opaque pointers for use by the caller.  The library will not touch
 these.
 
 
 Opaque pointers for use by the caller.  The library will not touch
 these.
 
- };
- typedef struct mexp_h mexp_h;
-
 =head1 CLOSING THE HANDLE
 
 To close the handle and clean up the subprocess, call:
 =head1 CLOSING THE HANDLE
 
 To close the handle and clean up the subprocess, call:
@@ -206,10 +261,10 @@ This is how code should check for and print errors from C<mexp_close>:
 =head1 EXPECT FUNCTION
 
 Miniexpect contains a powerful regular expression matching function
 =head1 EXPECT FUNCTION
 
 Miniexpect contains a powerful regular expression matching function
-based on L<pcre(3)>:
+based on L<pcre2(3)>:
 
 B<int mexp_expect (mexp_h *h, const mexp_regexp *regexps,
 
 B<int mexp_expect (mexp_h *h, const mexp_regexp *regexps,
-int *ovector, int ovecsize);>
+pcre2_match_data *match_data);>
 
 The output of the subprocess is matched against the list of PCRE
 regular expressions in C<regexps>.  C<regexps> is a list of regular
 
 The output of the subprocess is matched against the list of PCRE
 regular expressions in C<regexps>.  C<regexps> is a list of regular
@@ -217,8 +272,7 @@ expression structures:
 
  struct mexp_regexp {
    int r;
 
  struct mexp_regexp {
    int r;
-   const pcre *re;
-   const pcre_extra *extra;
+   const pcre2_code *re;
    int options;
  };
  typedef struct mexp_regexp mexp_regexp;
    int options;
  };
  typedef struct mexp_regexp mexp_regexp;
@@ -248,7 +302,7 @@ returned in C<errno>.
 
 =item C<MEXP_PCRE_ERROR>
 
 
 =item C<MEXP_PCRE_ERROR>
 
-There was a C<pcre_exec> error.  C<h-E<gt>pcre_error> is set to the
+There was a C<pcre2_match> error.  C<h-E<gt>pcre_error> is set to the
 error code.  See L<pcreapi(3)> for a list of the C<PCRE_*> error codes
 and what they mean.
 
 error code.  See L<pcreapi(3)> for a list of the C<PCRE_*> error codes
 and what they mean.
 
@@ -271,8 +325,8 @@ for EOF or timeout.
 
 =item *
 
 
 =item *
 
-C<regexps[].re>, C<regexps[].extra>, C<regexps[].options>, C<ovector>
-and C<ovecsize> are passed through to the L<pcre_exec(3)> function.
+C<regexps[].re>, C<regexps[].options> and C<match_data> are passed
+through to the L<pcre2_match(3)> function.
 
 =item *
 
 
 =item *
 
@@ -313,26 +367,29 @@ literal" and is available in C99.  If you need to use an older
 compiler, you can just use a local variable instead.
 
  mexp_h *h;
 compiler, you can just use a local variable instead.
 
  mexp_h *h;
char *errptr;
int errcode;
  int offset;
  int offset;
- pcre *password_re, *prompt_re;
- const int ovecsize = 12;
- int ovector[ovecsize];
+ pcre2_code *password_re, *prompt_re;
+ pcre2_match_data *match_data = pcre2_match_data_create (4, NULL);
  
  
- password_re = pcre_compile ("assword", 0, &errptr, &offset, NULL);
- prompt_re = pcre_compile ("[$#] ", 0, &errptr, &offset, NULL);
+ password_re = pcre2_compile ("assword", PCRE2_ZERO_TERMINATED,
+                              0, &errcode, &offset, NULL);
+ prompt_re = pcre2_compile ("[$#] ", PCRE2_ZERO_TERMINATED,
+                            0, &errcode, &offset, NULL);
  
  switch (mexp_expect (h,
                       (mexp_regexp[]) {
                         { 100, .re = password_re },
                         { 101, .re = prompt_re },
                         { 0 },
  
  switch (mexp_expect (h,
                       (mexp_regexp[]) {
                         { 100, .re = password_re },
                         { 101, .re = prompt_re },
                         { 0 },
-                      }, ovector, ovecsize)) {
+                      }, match_data)) {
   case 100:
   case 100:
-    /* here you would send a password */
+    /* server printed a password prompt, so send a password */
+    mexp_printf_password (h, "%s", password);
     break;
   case 101:
     break;
   case 101:
-    /* here you would send a command */
+    /* server sent a shell prompt, send a command */
+    mexp_printf (h, "ls\n");
     break;
   case MEXP_EOF:
     fprintf (stderr, "error: ssh closed the connection unexpectedly\n");
     break;
   case MEXP_EOF:
     fprintf (stderr, "error: ssh closed the connection unexpectedly\n");
@@ -355,6 +412,8 @@ However we also provide a convenience function:
 
 B<int mexp_printf (mexp_h *h, const char *fs, ...);>
 
 
 B<int mexp_printf (mexp_h *h, const char *fs, ...);>
 
+B<int mexp_printf_password (mexp_h *h, const char *fs, ...);>
+
 This returns the number of bytes, if the whole message was written OK.
 If there was an error, -1 is returned and the error is available in
 C<errno>.
 This returns the number of bytes, if the whole message was written OK.
 If there was an error, -1 is returned and the error is available in
 C<errno>.
@@ -375,8 +434,26 @@ send a command followed by a newline you have to do something like:
 
  mexp_printf (h, "exit\n");
 
 
  mexp_printf (h, "exit\n");
 
+=item *
+
+C<mexp_printf_password> works identically to C<mexp_printf> except
+that the output is I<not> sent to the debugging file if debugging is
+enabled.  As the name suggests, use this for passwords so that they
+don't appear in debugging output.
+
 =back
 
 =back
 
+B<int mexp_send_interrupt (mexp_h *h);>
+
+Send the interrupt character (C<^C>, Ctrl-C, C<\003>).  This is like
+pressing C<^C> - the subprocess (or remote process, if using C<ssh>)
+is gracefully killed.
+
+Note this only works if the pty is in cooked mode
+(ie. C<MEXP_SPAWN_COOKED_MODE> was passed to C<mexp_spawnlf> or
+C<mexp_spawnvf>).  In raw mode, all characters are passed through
+without any special interpretation.
+
 =head1 SOURCE
 
 Source is available from:
 =head1 SOURCE
 
 Source is available from:
@@ -384,9 +461,9 @@ L<http://git.annexia.org/?p=miniexpect.git;a=summary>
 
 =head1 SEE ALSO
 
 
 =head1 SEE ALSO
 
-L<pcre(3)>,
-L<pcre_exec(3)>,
-L<pcreapi(3)>,
+L<pcre2(3)>,
+L<pcre2_match(3)>,
+L<pcre2api(3)>,
 L<waitpid(2)>,
 L<system(3)>.
 
 L<waitpid(2)>,
 L<system(3)>.
 
@@ -401,4 +478,4 @@ your option any later version.
 
 =head1 COPYRIGHT
 
 
 =head1 COPYRIGHT
 
-Copyright (C) 2014 Red Hat Inc.
+Copyright (C) 2014-2022 Red Hat Inc.