UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

#1 2007-04-26 10:45 AM

bea
Member
Registered: 2007-04-26
Posts: 5

Re: sftp with expect.h

Hi! :)

I do have following problem and spent already quite a lot of time with it, also searching the internet, but pittily with no result :(

I need to use sftp with automatically passing the password and commands. For this I use expect - at the moment as script called by a c++ program. Now I want to optimize this "work around" using <expect.h> directly in my program.

A filepointer is created correctly using exp_popen, also the pattern match using exp_expectv works correctly. The only thing, which does not work, is writing the password. With fwrite I get the error message "Illegal seek". Somehow I do not find the error / the solution. Some hints or help would be great! :)

Thank you very much in advance!

Bea

And here's an example code of what I am doing:

#include <string>
#include <iostream>
#include <expect.h>

using namespace std;

int main(int argc, char** argv)
{
  exp_is_debugging  = 1;
  exp_loguser       = 0;
  exp_timeout       = 10; // timeout in seconds
 	
  // open sftp program
  FILE* fp = exp_popen( "sftp test@127.0.0.1" );
  if ( fp == NULL ) return 1;
  
  cout << "Process Id: " << exp_pid << endl;
  
  // "password:" is expected
  struct exp_case expectCase;
    
  expectCase.pattern  = "password:";
  expectCase.re       = NULL;
  expectCase.type     = exp_glob;
  expectCase.value    = 0; // value to be returned upon match 
  
  // get the file descriptor 
  int fd = fileno( fp );
  
  if ( exp_expectv( fd, &expectCase ) != 0 )
  { 
    cerr << expectCase.pattern << " does not match." << endl;
    return 1;
  }
  else
  {
  	cout << expectCase.pattern << " found." << endl;
  	
    char* buffer[] = { "test" };
    
    // enter the password automatically
    fwrite( buffer, sizeof( buffer[0] ), 1, fp );
    perror( "fwrite()" );
  }
  return 0;
}

Offline

#2 2007-04-26 11:19 AM

biologz
Administrator
From: Puking on the pavement
Registered: 2005-11-02
Posts: 396

Re: sftp with expect.h

Hi,

I don't think you're obliged to write your own program for that. There is a batch mode for sftp, you can use it like this:

sftp -b <batchfile> user@host

Maybe you should search for more information about that. The problem is i'm not sure you can automatically log in this way, you should use key authentification.

I edit my post because i found a clear example of how to do what you want but not using C. You should create a file and put the following line in it:

#!/usr/local/bin/expect

spawn  sftp  -b cmdFile user@yourserver.com
expect "password:"
send "shhh!\n";
interact

This will spawn sftp in batch mode and pass in the password shhh! to the program. SFTP will than execute all the commads in cmdFile. I found it here: http://linux-bsd-central.com/index.php/ … iew/26/29/

But if you really want to do that with C, i can't help you, but the man 3 libexepect seems to be quite complete.

Good luck


gethostbyintuition() is still a dream of mine

                                                 -- quoted from bash

Offline

#3 2007-04-26 12:19 PM

bea
Member
Registered: 2007-04-26
Posts: 5

Re: sftp with expect.h

Hi biologz,

thank you for your answer! :)

Well, the batchfile is working fine. Maybe I did not describe my problem clearly enough:

I need to download files via sftp. This should work automatically. Due to writing the file contents into a database, I wrote a C++ program calling an expect-script (for downloading), parsing the downloaded files and writing to database.
I start the script with a system call. The problem is that I do not know if the script stops e.g. due to connection failure or due to successful download.

I have built a workaround with a "valid"-file to find out if download was successful as well as a watchdog in case sftp does not return. I hoped, that there is a better solution. :-/

Offline

#4 2007-04-26 12:54 PM

biologz
Administrator
From: Puking on the pavement
Registered: 2005-11-02
Posts: 396

Re: sftp with expect.h

Well i'm still not sure why you're using a C program for that. I would only use shell script instead of C which is not needed for your problem (at least from what i understand).

Anyway maybe someone will have a better understanding than me or a different point of view.

But really if you have to download a file with SFTP then parse it and update a database, i would write a shell script using expect, then i'll still use shell script for parsing (with a program like awk) and then i'd you mysql to fill in the database.

Lol i realize this answer don't satisfy you so just wait for someone else to answer. The bosses of the forum will arrive soon i think, there are attracted by the smell of new posts like a lion is attracted by fresh meat ;-)


gethostbyintuition() is still a dream of mine

                                                 -- quoted from bash

Offline

#5 2007-04-26 01:17 PM

bea
Member
Registered: 2007-04-26
Posts: 5

Re: sftp with expect.h

I must admit, that I am not that good at shell scripting. I have only done some "easy" ones.

But I will consider your answer, maybe it's really a much better and easier solution. :smile:

Thank's anyway! :)

Offline

#6 2007-04-26 01:26 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,829
Website

Re: sftp with expect.h

Actually, instead of using libexpect and spawning the real "sftp", what I would
personally do from a C/C++ program is use the wonderful libcurl, which handles
SFTP, along with dozens of other protocols...

But, if you insist on doing it this way...  I suspect your problem stems from using
exp_expectv() with the raw FD, instead of using exp_fexpectv() with the stdio file
pointer...  Then, followed by the fwrite() with the file pointer...  It's always a bad idea
to mix I/O between raw FD and stdio; it's wise to pick either one or the other and
stick with it for all I/O...

Oh, and actually, this is just plain wrong:

char* buffer[] = { "test" };
    
    // enter the password automatically
    fwrite( buffer, sizeof( buffer[0] ), 1, fp );
    perror( "fwrite()" );

First of all, you're always perror()'ing, regardless of what fwrite() returns...  So, you
may be seeing spurious errors from left-over errnos, not real fwrite() failures at all...
But, the big problem is that your "buffer" is an array of POINTERS to char; ie., an
array of strings...  Where you just want a simple single string...  You want either:

char *buffer = "test\r\n";
/* or */
char buffer[] = "test\r\n";

Either will work, but you'll want to use strlen() instead of sizeof() for the former; in
fact, I think you want to use that for BOTH, since I don't think you really want to
write out the null char...  And, you'll see I added CRLF to the end, which I think you
will need, as well...  In fact, instead of fwrite(), I'd just use fputs(), myself...

Offline

#7 2007-04-26 03:06 PM

bea
Member
Registered: 2007-04-26
Posts: 5

Re: sftp with expect.h

Hi RobSeace,

I did not know libcurl before. It seems that only the newest version libcurl4 supports sftp, which is still experimental. But it seems worth to try :)

Concerning the expect - version:
Thanks for the hint with the perror - it was a copy-paste-thing to this test file :-/

Pittily the match does not work with

...
if ( exp_fexpectv( fp, &expectCase ) != 0 ) ...

It's crashing with a Segmentation fault. Maybe I miss something important :confused:

Thank you for your help!

Offline

#8 2007-04-26 09:39 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,829
Website

Re: sftp with expect.h

Oh, wait, yeah: exp_[f]expectv() both want an ARRAY of structs not just a pointer to
a single "exp_case" struct...  You need a second struct of type "exp_end" to mark
the end of the array...  Right now, you're reading off the end of your stack, which
is why you're crashing...  I don't know why exp_expectv() doesn't crash as well; just
pure luck to find the right value in your memory somewhere, I suspect...

You really need to take a closer read of "man libexpect", I think...

As for libcurl, I don't know about SFTP being "experimental" (where do you read
that?), but I know for a fact it works, because I actually ported a semi-recent version
to QNX4 a while back, and got it working there...  (It required some hackery to seed
the OpenSSL PRNG, since it won't auto-seed like on Linux, because there's no
"/dev/random" there...)

Offline

#9 2007-04-27 09:56 AM

bea
Member
Registered: 2007-04-26
Posts: 5

Re: sftp with expect.h

Thank you very much!!! Everything is working fine now! Great! :)

Have a nice weekend! :wink:

Offline

#10 2008-01-21 02:34 PM

gauravtiwari
Member
Registered: 2008-01-21
Posts: 2

Re: sftp with expect.h

I am trying to use libcurl to write a c code which does a sftp in batch mode but with password authentication, is there any way i can pass password on my own without asking it from user and also can someone please throw some light on how to use curl_easy_setopt() function to use it for my case.

Offline

#11 2008-01-21 08:07 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,829
Website

Re: sftp with expect.h

I think you could either set the username and password right in the URL using
standard syntax (eg: "sftp://user:Pass@hostname/"), or via CURLOPT_USERPWD...
So, eg:

curl_easy_setopt (curlhandle, CURLOPT_URL, "sftp://user:Pass@hostname/");
/* ...or... */
curl_easy_setopt (curlhandle, CURLOPT_USERPWD, "user:Pass");

Offline

#12 2008-01-22 09:02 AM

gauravtiwari
Member
Registered: 2008-01-21
Posts: 2

Re: sftp with expect.h

Thanks for the reply. I am not sure that whether sftp supports this sort password specifying in URL it self. I will try the other one. thanks again.

Offline

#13 2012-11-17 05:39 PM

omirp
Guest

Re: sftp with expect.h

Here is a blog about using expect script C/C++ library to manage Linux hosts.  I think it answers this question.

http://kahimyang.info/kauswagan/howto_b … inux_hosts

Board footer

Powered by FluxBB