Link to home
Start Free TrialLog in
Avatar of coryder
coryder

asked on

COMMUNICATING with FTP

i know that fstream allows communication with a file.  is there an equivalent class that would allow me to communicate likewise with the ftp program provided by UNIX.  

what i'm trying to do is write a program that acts as an interface to ftp.  it grabs info from a file, and then manipulates the ftp program accordingly.  meanwhile, i don't want anything printed on screen.  so i want to execute "ftp", and then get the response "ftp>" into a variable, and check it, then send back "open", and expect the response "(to):"...and so on.

i've tried using C function:
   popen("ftp", "rt");

but the problem with this is that i need to read back the response, i.e. "ftp>" when i send "ftp".  and i can get "ftp>" with something like: fgets, but fgets doesn't know when to stop reading because after "ftp>" nothing would be sent because ftp is waiting for a command, but fgets doesn't know that and it keeps trying to read.  i think i need to read nonblocked data or something.....not too sure.

anyway, help =)  a C++ solution that replaces the use of popen() would be most appreciated, and preferred.  but any other solution is welcomed.

thanks.
Avatar of jhance
jhance

If your client platform is Windows, you can use the MFC/WININET API to open an FTP connection.  See the docs on CFtpConnection.
Avatar of coryder

ASKER

sorry, i didn't specify.  i'm developing for interix.
Don't know about interix, but...

It sounds like you are trying to run your program on top of an FTP program you already have available.  Why not do what that FTP program does, and just talk directly with the FTP server through a socket?  FTP is a simple text-based protocol, and there's a plethora of sample code around in many languages.

Of course, reinventing the wheel is not usually a great idea - have you searched for a toolkit that provides libraries to simplify your program's use of FTP?

If you write your own, your code will basically open a socket to the FTP server, then alternate sending commands or data and waiting for responses.

Hope this helps.
Avatar of coryder

ASKER

thanks for the suggestion azami.  i've searched on the net for C/C++ sample code but haven't had any luck.  maybe i'm just bad at searching.  i'll keep looking tho.  thanks.  off the top of your head, do you know of any sites that provide source code for things like FTP?
Hmmm, a simple search doesn't seem to turn up much.  Guess I spoke too optimistically.  The code I've seen came with a book and was very helpful (I'll comment again when I figure out what the book was).

For books, you might look under Network Programming at Amazon or your local bookseller.  The one we had was for Windows, but the algorithms were actually more generic than that - they'd just need to be modified to use whatever sockets API you have rather than Winsock.

For free example code, look at http://www.itprc.com/tcpipfaq/faq-1.htm#source-apps. This has links to some core TCP/IP program source; probably more complex than you're needing, but may be helpful.

FTP (the protocol itself) is described in RFC172 (ftp://ftp.isi.edu/in-notes/rfc172.txt), which is rather dry reading.  Hopefully you can find a book that provides the information you need more clearly.

I'll post a new comment when I figure out what the book was we got code from (that was at a previous job, so I don't have the code handy to offer).
Avatar of coryder

ASKER

thanks so much =)
If you want to control the ftp data transfer and have an ftp server available on both platforms, you can do this using two telnet connections and use something called a proxy transfer.  You create a telnet connection to both servers and tell one to wait for a file, the otherone to send a file.  This avoids the need to implement the ftp client/server data exchange protocol.  See following PAQ for more info on the commands to use:
https://www.experts-exchange.com/jsp/qShow.jsp?ta=unixnet&qid=10052364 
For ftp and ftpd example code, look in any linux site or www.gnu.org
The book is "Developing for the Internet with Winsock" by Dave Roberts.
http://www.private.org.il/tcpip_rl.html

This site is a TCP/IP resource list, and appears to include links and info about books, toolkits, and lots more.  Covers protocols and sockets programming both.  I haven't examined it thoroughly, but it looks helpful in that it provides a synopsis for each link so you don't spend forever following useless links.

Good luck!
Avatar of coryder

ASKER

thanks for the pointer azami.  i'm playing with pipe(), fork() and  execl().  if i have to resort to FTP code, i'll definitely rumage thru those links.

thanks for the suggestion bertvermeerbergen, but the telnet thing is not what i'm looking for.
Ok, I understand that you want to try the other solution(s) first. I tried it myself also, but never really got the level of control I needed (you get to control 95%, but the remaining 5% is the reason I needed the control...)
Just keep in mind that the 'telnet' I was talking about has nothing to do with the telnet program.  In fact, what azami is proposing with the socket solution is the same thing.  The control connection in an ftp protocol uses the 'telnet' protocol.  This is just a way of saying that you send a line delimited with LF as a command (with a few options).  What I meant was that you can get away with writing just this part of an ftp client and don't need to bother with the data transfer and file handling and I/O.  In the PAQ I mentioned, the telnet program is used to simulate what a C program could do.  Such a program is very simple to write.
Avatar of coryder

ASKER

i understand.  and thanks.  once again.
To do this without writing an FTP client, you ought to be able to manage it with pipes (or socketpairs) and forking or execing.  I guess the "classic" way to do this in UNIX is (in pseudocode)

create pipe1
create pipe2

if ((pid = fork()) < 0)
   //error
else if (pid > 0)
   //parent
   close pipe1's read end
   close pipe2's write end
   do real work - write to pipe1 and read from pipe2
else
   //child
   close pipe1's write end
   close pipe2's read end
   dup2() pipe1 to stdin
   dup2() pipe2 to stdout
   exec other program (e.g. FTP) such that it inherits handles

There may be a form of exec, spawn, etc. that let's you specifically pass handles to use for stdin/stdout, in which case you don't need the fork rigamarole.  The point is, your code creates two pipes.  The first pipe, your code writes into one end and the other end is FTP's stdin.  For the other pipe, your code reads from one end and the other end is FTP's stdout.
I'm not familiar with interix.  I assume it's a flavor of UNIX.  If so, ftp can use redirection of stdin/stdout.  For simple automation, I've used scripts to build "command" files for ftp, then invoked ftp with stdin redirected from the command file and stdout redirected to a log file.

If you really need the ftp source code you can get GNU ftp from the GNU site:

www.gnu.org
Avatar of coryder

ASKER

azami, thx.  that's what i was trying yesterday.  still working on it.  still keeping all the options in mind.  thx all.  
Avatar of coryder

ASKER

azami,

my code wasn't working, and i tried the "classic method" you described in pseudocode, and i still couldn't read from the pipe.  could you lend a hand.  submit an answer, i'll send the points.


enum PIPES { READ, WRITE };

int main()
{
      int      h_child_pipe[2] = {0};
      
      char      buf[256] = {0};

      FILE      *child_instream;
      FILE      *child_outstream;

      long      flags = 0;
      

      pipe(h_child_pipe);

      int pid = fork();

      if (pid < 0)
      {
                            // error
      }      
      else if (pid == 0)
      {
            // child process
            //
            
            close(h_child_pipe[READ]);
            close(h_child_pipe[WRITE]);

            dup2(fileno(stdout), h_child_pipe[READ]);
            dup2(fileno(stdin), h_child_pipe[WRITE]);

            execlp("ls", "", 0);
      }
      else if (pid > 0)
      {
            cout << "in parent" << endl;

            // parent
            //
            
            close(h_child_pipe[READ]);
            close(h_child_pipe[WRITE]);

            child_instream = fdopen(h_child_pipe[READ], "r");
      
                     child_outstream = fdopen(h_child_pipe[WRITE], "w");
            
            fread(buf, 255, 1, child_instream);

            printf("printf buf is: <%s>", buf);

                    cout << "fread read: <" << buf << ">" << endl;

      }

      return(0);
}
ASKER CERTIFIED SOLUTION
Avatar of azami
azami
Flag of Japan image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of coryder

ASKER

thanks.  that helped lots. =)