/* miniexpect example.
- * 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
* The remaining arguments are passed to the ssh subprocess.
*
* For example:
- * sshpass 123456 ssh remote.example.com
- * sshpass 123456 ssh -l root remote.example.com
+ * sshpass [-d] 123456 ssh remote.example.com
+ * sshpass [-d] 123456 ssh -l root remote.example.com
+ *
+ * Use the -d flag to enable debugging to stderr.
*/
#include <config.h>
#include <unistd.h>
#include <assert.h>
-#include <pcre.h>
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
#include "miniexpect.h"
-static pcre *compile_re (const char *rex);
+static pcre2_code *compile_re (const char *rex);
+
+static void
+usage (void)
+{
+ fprintf (stderr, "usage: sshpass [-d] PASSWORD ssh [SSH-ARGS...] HOST\n");
+ exit (EXIT_FAILURE);
+}
int
main (int argc, char *argv[])
{
+ int opt;
+ int debug = 0;
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;
- if (argc <= 3) {
- fprintf (stderr, "usage: sshpass PASSWORD ssh [SSH-ARGS...] HOST\n");
- exit (EXIT_FAILURE);
+ match_data = pcre2_match_data_create (4, NULL);
+
+ while ((opt = getopt (argc, argv, "d")) != -1) {
+ switch (opt) {
+ case 'd':
+ debug = 1;
+ break;
+ default:
+ usage ();
+ }
}
- password = argv[1];
+ if (argc-optind <= 2)
+ usage ();
+
+ password = argv[optind];
+ optind++;
printf ("starting ssh command ...\n");
- h = mexp_spawnv (argv[2], &argv[2]);
+ h = mexp_spawnv (argv[optind], &argv[optind]);
if (h == NULL) {
perror ("mexp_spawnv: ssh");
exit (EXIT_FAILURE);
}
+ if (debug)
+ mexp_set_debug_file (h, stderr);
/* Wait for the password prompt. */
password_re = compile_re ("assword");
{ 100, .re = password_re },
{ 0 }
},
- ovector, ovecsize)) {
+ match_data)) {
case 100:
break;
case MEXP_EOF:
goto error;
}
- /* Got the password prompt, so send a password. */
+ /* Got the password prompt, so send a password.
+ *
+ * Note use of mexp_printf_password here which is identical to
+ * mexp_printf except that it hides the password in debugging
+ * output.
+ */
printf ("sending the password ...\n");
- if (mexp_printf (h, "%s\n", password) == -1) {
+ if (mexp_printf_password (h, "%s", password) == -1 ||
+ mexp_printf (h, "\n") == -1) {
perror ("mexp_printf");
goto error;
}
{ 101, .re = prompt_re },
{ 0 },
},
- ovector, ovecsize)) {
+ match_data)) {
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 },
},
- ovector, ovecsize)) {
+ match_data)) {
case 100:
break;
case MEXP_EOF:
goto error;
}
- 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;
printf ("test was successful\n");
+ pcre2_match_data_free (match_data);
exit (EXIT_SUCCESS);
error:
}
/* Helper function to compile a PCRE regexp. */
-static pcre *
+static pcre2_code *
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);
if (ret == 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;