X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=example-sshpass.c;h=7130ac8b9e5794dd41d04a2edb7b86d9a5c0c2c9;hb=b300de9ac244ef5fd315228bce69c2b938dc77f4;hp=a35c1d41f68e9c7845dcf476ca174a167c8a9665;hpb=5cac23de1963880d8fb3aed4be47ec2894cf520c;p=miniexpect.git diff --git a/example-sshpass.c b/example-sshpass.c index a35c1d4..7130ac8 100644 --- a/example-sshpass.c +++ b/example-sshpass.c @@ -1,5 +1,5 @@ /* 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 @@ -24,8 +24,10 @@ * 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 @@ -36,75 +38,93 @@ #include #include -#include +#define PCRE2_CODE_UNIT_WIDTH 8 +#include #include "miniexpect.h" -static pcre * -compile_re (const char *rex) -{ - const char *errptr; - int erroffset; - pcre *ret; +static pcre2_code *compile_re (const char *rex); - ret = pcre_compile (rex, 0, &errptr, &erroffset, NULL); - if (ret == NULL) { - fprintf (stderr, "error: failed to compile regular expression '%s': %s at offset %d\n", - rex, errptr, erroffset); - exit (EXIT_FAILURE); - } - return ret; +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]; - int pcre_err; + 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 ("ssh", &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"); - switch (mexp_expect (h, password_re, NULL, 0, ovector, ovecsize, &pcre_err)) { + switch (mexp_expect (h, + (mexp_regexp[]) { + { 100, .re = password_re }, + { 0 } + }, + match_data)) { + case 100: + break; case MEXP_EOF: fprintf (stderr, "error: ssh closed the connection unexpectedly\n"); goto error; - case MEXP_ERROR: - perror ("mexp_expect"); - goto error; case MEXP_TIMEOUT: fprintf (stderr, "error: timeout before reaching the password prompt\n"); goto error; + case MEXP_ERROR: + perror ("mexp_expect"); + goto error; case MEXP_PCRE_ERROR: - fprintf (stderr, "error: PCRE error: %d\n", pcre_err); + fprintf (stderr, "error: PCRE error: %d\n", mexp_get_pcre_error (h)); goto error; - case MEXP_MATCHED: - break; } - /* 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; } @@ -115,31 +135,31 @@ main (int argc, char *argv[]) * expect checks all these possibilities. Unfortunately since all * prompts are a little bit different, we have to guess here. */ - prompt_re = compile_re ("(assword)|([#$])"); - switch (mexp_expect (h, prompt_re, NULL, 0, ovector, ovecsize, &pcre_err)) { + prompt_re = compile_re ("[#$]"); + switch (mexp_expect (h, + (mexp_regexp[]) { + { 100, .re = password_re }, + { 101, .re = prompt_re }, + { 0 }, + }, + match_data)) { + case 100: /* Password. */ + fprintf (stderr, "error: ssh asked for password again, probably the password supplied is wrong\n"); + goto error; + case 101: /* Prompt. */ + break; case MEXP_EOF: fprintf (stderr, "error: ssh closed the connection unexpectedly\n"); goto error; - case MEXP_ERROR: - perror ("mexp_expect"); - goto error; case MEXP_TIMEOUT: fprintf (stderr, "error: timeout before reaching the prompt\n"); goto error; + case MEXP_ERROR: + perror ("mexp_expect"); + goto error; case MEXP_PCRE_ERROR: - fprintf (stderr, "error: PCRE error: %d\n", pcre_err); + fprintf (stderr, "error: PCRE error: %d\n", mexp_get_pcre_error (h)); goto error; - case MEXP_MATCHED: - /* Which part of the regexp matched? */ - if (ovector[2] >= 0) { /* password */ - fprintf (stderr, "error: ssh asked for password again, probably the password supplied is wrong\n"); - goto error; - } - else if (ovector[4] >= 0) { /* prompt */ - break; - } - else - abort (); /* shouldn't happen */ } /* Send a command which will have expected output. */ @@ -152,21 +172,26 @@ main (int argc, char *argv[]) /* Wait for expected output from echo hello command. */ hello_re = compile_re ("hello"); - switch (mexp_expect (h, hello_re, NULL, 0, ovector, ovecsize, &pcre_err)) { + switch (mexp_expect (h, + (mexp_regexp[]) { + { 100, .re = hello_re }, + { 0 }, + }, + match_data)) { + case 100: + break; case MEXP_EOF: fprintf (stderr, "error: ssh closed the connection unexpectedly\n"); goto error; - case MEXP_ERROR: - perror ("mexp_expect"); - goto error; case MEXP_TIMEOUT: fprintf (stderr, "error: timeout before reading command output\n"); goto error; + case MEXP_ERROR: + perror ("mexp_expect"); + goto error; case MEXP_PCRE_ERROR: - fprintf (stderr, "error: PCRE error: %d\n", pcre_err); + fprintf (stderr, "error: PCRE error: %d\n", mexp_get_pcre_error (h)); goto error; - case MEXP_MATCHED: - break; } /* Send exit command and wait for ssh to exit. */ @@ -177,18 +202,17 @@ main (int argc, char *argv[]) goto error; } - switch (mexp_expect (h, NULL, NULL, 0, NULL, 0, NULL)) { + switch (mexp_expect (h, NULL, NULL)) { case MEXP_EOF: /* This is what we're expecting: ssh will close the connection. */ break; - case MEXP_ERROR: - perror ("mexp_expect"); - goto error; case MEXP_TIMEOUT: fprintf (stderr, "error: timeout before ssh closed the connection\n"); goto error; + case MEXP_ERROR: + perror ("mexp_expect"); + goto error; case MEXP_PCRE_ERROR: - case MEXP_MATCHED: fprintf (stderr, "error: unexpected return value from mexp_expect\n"); goto error; } @@ -203,9 +227,33 @@ main (int argc, char *argv[]) printf ("test was successful\n"); + pcre2_match_data_free (match_data); exit (EXIT_SUCCESS); error: mexp_close (h); exit (EXIT_FAILURE); } + +/* Helper function to compile a PCRE regexp. */ +static pcre2_code * +compile_re (const char *rex) +{ + int errorcode; + PCRE2_SIZE erroroffset; + char errormsg[256]; + pcre2_code *ret; + + ret = pcre2_compile ((PCRE2_SPTR) rex, PCRE2_ZERO_TERMINATED, + 0, &errorcode, &erroroffset, NULL); + if (ret == NULL) { + 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; +}