summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
6a57e58)
The last version of PCRE (v1) 8.45 is end of life and will receive no
more updates. PCRE2 is its replacement and is widely available in
distros. So port the library to PCRE2.
lib_LTLIBRARIES = libminiexpect.la
libminiexpect_la_SOURCES = miniexpect.c miniexpect.h
lib_LTLIBRARIES = libminiexpect.la
libminiexpect_la_SOURCES = miniexpect.c miniexpect.h
-libminiexpect_la_CFLAGS = $(PCRE_CFLAGS) -Wall
-libminiexpect_la_LIBADD = $(PCRE_LIBS)
+libminiexpect_la_CFLAGS = $(PCRE2_CFLAGS) -Wall
+libminiexpect_la_LIBADD = $(PCRE2_LIBS)
libminiexpect_la_LDFLAGS = -version-info 0:0:0
# Examples.
libminiexpect_la_LDFLAGS = -version-info 0:0:0
# Examples.
noinst_PROGRAMS = example-sshpass
example_sshpass_SOURCES = example-sshpass.c
noinst_PROGRAMS = example-sshpass
example_sshpass_SOURCES = example-sshpass.c
-example_sshpass_CFLAGS = $(PCRE_CFLAGS) -Wall
+example_sshpass_CFLAGS = $(PCRE2_CFLAGS) -Wall
example_sshpass_LDADD = libminiexpect.la
# Tests.
example_sshpass_LDADD = libminiexpect.la
# Tests.
test-multi-match
test_spawn_SOURCES = test-spawn.c tests.h miniexpect.h
test-multi-match
test_spawn_SOURCES = test-spawn.c tests.h miniexpect.h
-test_spawn_CFLAGS = $(PCRE_CFLAGS) -Wall
+test_spawn_CFLAGS = $(PCRE2_CFLAGS) -Wall
test_spawn_LDADD = libminiexpect.la
test_ls_version_SOURCES = test-ls-version.c tests.h miniexpect.h
test_spawn_LDADD = libminiexpect.la
test_ls_version_SOURCES = test-ls-version.c tests.h miniexpect.h
-test_ls_version_CFLAGS = $(PCRE_CFLAGS) -Wall
+test_ls_version_CFLAGS = $(PCRE2_CFLAGS) -Wall
test_ls_version_LDADD = libminiexpect.la
test_multi_match_SOURCES = test-multi-match.c tests.h miniexpect.h
test_ls_version_LDADD = libminiexpect.la
test_multi_match_SOURCES = test-multi-match.c tests.h miniexpect.h
-test_multi_match_CFLAGS = $(PCRE_CFLAGS) -Wall
+test_multi_match_CFLAGS = $(PCRE2_CFLAGS) -Wall
test_multi_match_LDADD = libminiexpect.la
# parallel-tests breaks the ability to put 'valgrind' into
test_multi_match_LDADD = libminiexpect.la
# parallel-tests breaks the ability to put 'valgrind' into
It has a saner interface than libexpect, and doesn't depend on Tcl.
It is also thread safe, const-correct and uses modern C standards.
It has a saner interface than libexpect, and doesn't depend on Tcl.
It is also thread safe, const-correct and uses modern C standards.
-It is standalone, except that it requires the PCRE (Perl Compatible
-Regular Expressions) library from http://www.pcre.org/. The PCRE
+It is standalone, except that it requires the PCRE2 (Perl Compatible
+Regular Expressions) library from http://www.pcre.org/. The PCRE2
dependency is fundamental because we want to offer the most powerful
regular expression syntax to match on, but more importantly because
dependency is fundamental because we want to offer the most powerful
regular expression syntax to match on, but more importantly because
-PCRE has a convenient way to detect partial matches which made this
+PCRE2 has a convenient way to detect partial matches which made this
library very simple to implement.
License
library very simple to implement.
License
-# Copyright (C) 2014 Red Hat Inc.
+# Copyright (C) 2014-2022 Red Hat Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-AC_INIT([miniexpect],[1.0])
+AC_INIT([miniexpect],[1.1])
AM_INIT_AUTOMAKE(foreign) dnl NB: Do not [quote] this parameter.
AM_INIT_AUTOMAKE(foreign) dnl NB: Do not [quote] this parameter.
dnl Check support for 64 bit file offsets.
AC_SYS_LARGEFILE
dnl Check support for 64 bit file offsets.
AC_SYS_LARGEFILE
-dnl The only dependency is libpcre (Perl Compatible Regular Expressions).
-PKG_CHECK_MODULES([PCRE], [libpcre])
+dnl The only dependency is libpcre2 (Perl Compatible Regular Expressions).
+PKG_CHECK_MODULES([PCRE2], [libpcre2-8])
dnl Optional for building the manual page. This is part of Perl.
AC_CHECK_PROG([POD2MAN], [pod2man], [pod2man], [no])
dnl Optional for building the manual page. This is part of Perl.
AC_CHECK_PROG([POD2MAN], [pod2man], [pod2man], [no])
- * Copyright (C) 2014 Red Hat Inc.
+ * Copyright (C) 2014-2022 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <unistd.h>
#include <assert.h>
#include <unistd.h>
#include <assert.h>
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
-static pcre *compile_re (const char *rex);
+static pcre2_code *compile_re (const char *rex);
mexp_h *h;
const char *password;
int status;
mexp_h *h;
const char *password;
int status;
- pcre *password_re, *prompt_re, *hello_re;
- const int ovecsize = 12;
- int ovector[ovecsize];
+ pcre2_code *password_re, *prompt_re, *hello_re;
+ pcre2_match_data *match_data;
+
+ match_data = pcre2_match_data_create (4, NULL);
while ((opt = getopt (argc, argv, "d")) != -1) {
switch (opt) {
while ((opt = getopt (argc, argv, "d")) != -1) {
switch (opt) {
{ 100, .re = password_re },
{ 0 }
},
{ 100, .re = password_re },
{ 0 }
},
case 100:
break;
case MEXP_EOF:
case 100:
break;
case MEXP_EOF:
{ 101, .re = prompt_re },
{ 0 },
},
{ 101, .re = prompt_re },
{ 0 },
},
case 100: /* Password. */
fprintf (stderr, "error: ssh asked for password again, probably the password supplied is wrong\n");
goto error;
case 100: /* Password. */
fprintf (stderr, "error: ssh asked for password again, probably the password supplied is wrong\n");
goto error;
{ 100, .re = hello_re },
{ 0 },
},
{ 100, .re = hello_re },
{ 0 },
},
case 100:
break;
case MEXP_EOF:
case 100:
break;
case MEXP_EOF:
- switch (mexp_expect (h, NULL, NULL, 0)) {
+ switch (mexp_expect (h, NULL, NULL)) {
case MEXP_EOF:
/* This is what we're expecting: ssh will close the connection. */
break;
case MEXP_EOF:
/* This is what we're expecting: ssh will close the connection. */
break;
printf ("test was successful\n");
printf ("test was successful\n");
+ pcre2_match_data_free (match_data);
exit (EXIT_SUCCESS);
error:
exit (EXIT_SUCCESS);
error:
}
/* Helper function to compile a PCRE regexp. */
}
/* Helper function to compile a PCRE regexp. */
compile_re (const char *rex)
{
compile_re (const char *rex)
{
- const char *errptr;
- int erroffset;
- pcre *ret;
+ int errorcode;
+ PCRE2_SIZE erroroffset;
+ char errormsg[256];
+ pcre2_code *ret;
- ret = pcre_compile (rex, 0, &errptr, &erroffset, NULL);
+ ret = pcre2_compile ((PCRE2_SPTR) rex, PCRE2_ZERO_TERMINATED,
+ 0, &errorcode, &erroroffset, NULL);
- fprintf (stderr, "error: failed to compile regular expression '%s': %s at offset %d\n",
- rex, errptr, erroffset);
+ pcre2_get_error_message (errorcode,
+ (PCRE2_UCHAR *) errormsg, sizeof errormsg);
+ fprintf (stderr, "error: "
+ "failed to compile regular expression '%s': "
+ "%s at offset %zu\n",
+ rex, errormsg, erroroffset);
exit (EXIT_FAILURE);
}
return ret;
exit (EXIT_FAILURE);
}
return ret;
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/time.h>
-#include <pcre.h>
-
-/* RHEL 6 pcre did not define PCRE_PARTIAL_SOFT. However PCRE_PARTIAL
- * is a synonym so use that.
- */
-#ifndef PCRE_PARTIAL_SOFT
-#define PCRE_PARTIAL_SOFT PCRE_PARTIAL
-#endif
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
-mexp_expect (mexp_h *h, const mexp_regexp *regexps, int *ovector, int ovecsize)
+mexp_expect (mexp_h *h, const mexp_regexp *regexps,
+ pcre2_match_data *match_data)
{
time_t start_t, now_t;
int timeout;
{
time_t start_t, now_t;
int timeout;
assert (h->buffer != NULL);
for (i = 0; regexps[i].r > 0; ++i) {
assert (h->buffer != NULL);
for (i = 0; regexps[i].r > 0; ++i) {
- const int options = regexps[i].options | PCRE_PARTIAL_SOFT;
+ const int options = regexps[i].options | PCRE2_PARTIAL_SOFT;
- r = pcre_exec (regexps[i].re, regexps[i].extra,
- h->buffer, (int)h->len, 0,
- options,
- ovector, ovecsize);
+ r = pcre2_match (regexps[i].re,
+ (PCRE2_SPTR) h->buffer, (int)h->len, 0,
+ options, match_data, NULL);
h->pcre_error = r;
if (r >= 0) {
/* A full match. */
h->pcre_error = r;
if (r >= 0) {
/* A full match. */
- if (ovector != NULL && ovecsize >= 1 && ovector[1] >= 0)
+ const PCRE2_SIZE *ovector = NULL;
+
+ if (match_data)
+ ovector = pcre2_get_ovector_pointer (match_data);
+
+ if (ovector != NULL && ovector[1] >= 0)
h->next_match = ovector[1];
else
h->next_match = -1;
h->next_match = ovector[1];
else
h->next_match = -1;
- else if (r == PCRE_ERROR_NOMATCH) {
+ else if (r == PCRE2_ERROR_NOMATCH) {
/* No match at all. */
/* (nothing here) */
}
/* No match at all. */
/* (nothing here) */
}
- else if (r == PCRE_ERROR_PARTIAL) {
+ else if (r == PCRE2_ERROR_PARTIAL) {
/* Partial match. Keep the buffer and keep reading. */
can_clear_buffer = 0;
}
/* Partial match. Keep the buffer and keep reading. */
can_clear_buffer = 0;
}
- * Copyright (C) 2014 Red Hat Inc.
+ * Copyright (C) 2014-2022 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
/* This handle is created per subprocess that is spawned. */
struct mexp_h {
/* This handle is created per subprocess that is spawned. */
struct mexp_h {
/* Expect. */
struct mexp_regexp {
int r;
/* Expect. */
struct mexp_regexp {
int r;
- const pcre *re;
- const pcre_extra *extra;
int options;
};
typedef struct mexp_regexp mexp_regexp;
int options;
};
typedef struct mexp_regexp mexp_regexp;
};
extern int mexp_expect (mexp_h *h, const mexp_regexp *regexps,
};
extern int mexp_expect (mexp_h *h, const mexp_regexp *regexps,
- int *ovector, int ovecsize);
+ pcre2_match_data *match_data);
/* Sending commands, keypresses. */
extern int mexp_printf (mexp_h *h, const char *fs, ...)
/* Sending commands, keypresses. */
extern int mexp_printf (mexp_h *h, const char *fs, ...)
#include <errno.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/wait.h>
+ #define PCRE2_CODE_UNIT_WIDTH 8
+ #include <pcre2.h>
#include <miniexpect.h>
mexp_h *h;
h = mexp_spawnl ("ssh", "ssh", "host", NULL);
#include <miniexpect.h>
mexp_h *h;
h = mexp_spawnl ("ssh", "ssh", "host", NULL);
- switch (mexp_expect (h, regexps, ovector, ovecsize)) {
+ switch (mexp_expect (h, regexps, match_data)) {
- cc prog.c -o prog -lminiexpect -lpcre
+ cc prog.c -o prog -lminiexpect -lpcre2-8
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
B<int mexp_get_pcre_error (mexp *h);>
When C<mexp_expect> [see below] calls the PCRE function
B<int mexp_get_pcre_error (mexp *h);>
When C<mexp_expect> [see below] calls the PCRE function
-L<pcre_exec(3)>, it stashes the return value in the C<pcre_error>
+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.
field in the handle, and that field is returned by this method.
-There are two uses for this:
-
-=over 4
-
-=item 1.
-
If C<mexp_expect> returns C<MEXP_PCRE_ERROR>, then the actual PCRE
If C<mexp_expect> returns C<MEXP_PCRE_ERROR>, then the actual PCRE
-error code returned by L<pcre_exec(3)> is available by calling this
-method. For a list of PCRE error codes, see L<pcreapi(3)>.
-
-=item 2.
-
-A more unusual use is if you ever need to get the captured substrings
-from your regular expression (calling L<pcre_get_substring(3)>). The
-third parameter of that function (C<stringcount>) is the value
-returned by L<pcre_exec(3)>, and so you can call it like this:
-
- pcre_get_substring (h->buffer, ovector,
- mexp_get_pcre_error (h), 1, &matched);
-
-=back
+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<void mexp_set_debug_file (mexp *h, FILE *fp);>
=head1 EXPECT FUNCTION
Miniexpect contains a powerful regular expression matching function
=head1 EXPECT FUNCTION
Miniexpect contains a powerful regular expression matching function
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
struct mexp_regexp {
int r;
struct mexp_regexp {
int r;
- const pcre *re;
- const pcre_extra *extra;
int options;
};
typedef struct mexp_regexp mexp_regexp;
int options;
};
typedef struct mexp_regexp mexp_regexp;
-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.
mexp_h *h;
char *errptr;
int offset;
mexp_h *h;
char *errptr;
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 = pcre_compile ("assword", 0, &errptr, &offset, NULL);
prompt_re = pcre_compile ("[$#] ", 0, &errptr, &offset, NULL);
{ 100, .re = password_re },
{ 101, .re = prompt_re },
{ 0 },
{ 100, .re = password_re },
{ 101, .re = prompt_re },
{ 0 },
- }, ovector, ovecsize)) {
case 100:
/* here you would send a password */
break;
case 100:
/* here you would send a password */
break;
-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)>.
-Copyright (C) 2014 Red Hat Inc.
+Copyright (C) 2014-2022 Red Hat Inc.
#include <unistd.h>
#include <assert.h>
#include <unistd.h>
#include <assert.h>
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
#include "miniexpect.h"
#include "tests.h"
#include "miniexpect.h"
#include "tests.h"
{
mexp_h *h;
int status, r;
{
mexp_h *h;
int status, r;
- pcre *ls_coreutils_re;
- pcre *ls_busybox_re;
- const int ovecsize = 12;
- int ovector[ovecsize];
- const char *version;
+ pcre2_code *ls_coreutils_re;
+ pcre2_code *ls_busybox_re;
+ pcre2_match_data *match_data = pcre2_match_data_create (4, NULL);
+ PCRE2_UCHAR *version;
+ PCRE2_SIZE verlen;
ls_coreutils_re = test_compile_re ("^ls.* ([.\\d]+)");
/* Busybox doesn't actually recognize the --version option, but
ls_coreutils_re = test_compile_re ("^ls.* ([.\\d]+)");
/* Busybox doesn't actually recognize the --version option, but
{ 100, ls_coreutils_re },
{ 101, ls_busybox_re },
{ 0 },
{ 100, ls_coreutils_re },
{ 101, ls_busybox_re },
{ 0 },
- }, ovector, ovecsize)) {
case 100:
case 101:
/* Get the matched version number. */
case 100:
case 101:
/* Get the matched version number. */
- r = pcre_get_substring (h->buffer, ovector,
- mexp_get_pcre_error (h), 1, &version);
+ r = pcre2_substring_get_bynumber (match_data, 1, &version, &verlen);
if (r < 0) {
fprintf (stderr, "error: PCRE error reading version substring: %d\n",
r);
exit (EXIT_FAILURE);
}
if (r < 0) {
fprintf (stderr, "error: PCRE error reading version substring: %d\n",
r);
exit (EXIT_FAILURE);
}
- printf ("ls version = %s\n", version);
- pcre_free_substring (version);
+ printf ("ls version = %s\n", (char *) version);
+ pcre2_substring_free (version);
break;
case MEXP_EOF:
fprintf (stderr, "error: EOF before matching version string\n");
break;
case MEXP_EOF:
fprintf (stderr, "error: EOF before matching version string\n");
- pcre_free (ls_coreutils_re);
- pcre_free (ls_busybox_re);
+ pcre2_code_free (ls_coreutils_re);
+ pcre2_code_free (ls_busybox_re);
+ pcre2_match_data_free (match_data);
int r;
int rv[5];
size_t i;
int r;
int rv[5];
size_t i;
- pcre *multi_re = test_compile_re ("multi");
- pcre *match_re = test_compile_re ("match");
- pcre *ing_re = test_compile_re ("ing");
- pcre *str_re = test_compile_re ("str");
- pcre *s_re = test_compile_re ("s");
- const int ovecsize = 12;
- int ovector[ovecsize];
+ pcre2_code *multi_re = test_compile_re ("multi");
+ pcre2_code *match_re = test_compile_re ("match");
+ pcre2_code *ing_re = test_compile_re ("ing");
+ pcre2_code *str_re = test_compile_re ("str");
+ pcre2_code *s_re = test_compile_re ("s");
+ pcre2_match_data *match_data = pcre2_match_data_create (4, NULL);
/* If the subprocess prints multiple things, we should be able to
* repeatedly call mexp_expect to match on each one. This didn't
/* If the subprocess prints multiple things, we should be able to
* repeatedly call mexp_expect to match on each one. This didn't
{ 103, str_re },
{ 104, s_re },
{ 0 },
{ 103, str_re },
{ 104, s_re },
{ 0 },
switch (r) {
case 100: case 101: case 102: case 103: case 104:
printf ("iteration %zu: matched %d\n", i, r);
switch (r) {
case 100: case 101: case 102: case 103: case 104:
printf ("iteration %zu: matched %d\n", i, r);
- * Copyright (C) 2014 Red Hat Inc.
+ * Copyright (C) 2014-2022 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
fprintf (stderr, "stopped by signal %d", WSTOPSIG (status));
}
fprintf (stderr, "stopped by signal %d", WSTOPSIG (status));
}
+__attribute__((__unused__))
+static pcre2_code *
test_compile_re (const char *rex)
{
test_compile_re (const char *rex)
{
- const char *errptr;
- int erroffset;
- pcre *ret;
+ int errorcode;
+ PCRE2_SIZE erroroffset;
+ char errormsg[256];
+ pcre2_code *ret;
- ret = pcre_compile (rex, 0, &errptr, &erroffset, NULL);
+ ret = pcre2_compile ((PCRE2_SPTR) rex, PCRE2_ZERO_TERMINATED,
+ 0, &errorcode, &erroroffset, NULL);
- fprintf (stderr, "error: failed to compile regular expression '%s': %s at offset %d\n",
- rex, errptr, erroffset);
+ pcre2_get_error_message (errorcode,
+ (PCRE2_UCHAR *) errormsg, sizeof errormsg);
+ fprintf (stderr, "error: "
+ "failed to compile regular expression '%s': "
+ "%s at offset %zu\n",
+ rex, errormsg, erroroffset);
exit (EXIT_FAILURE);
}
return ret;
exit (EXIT_FAILURE);
}
return ret;