• C

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.
coryderAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jhanceCommented:
If your client platform is Windows, you can use the MFC/WININET API to open an FTP connection.  See the docs on CFtpConnection.
0
coryderAuthor Commented:
sorry, i didn't specify.  i'm developing for interix.
0
azamiCommented:
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.
0
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

coryderAuthor Commented:
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?
0
azamiCommented:
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).
0
coryderAuthor Commented:
thanks so much =)
0
bertvermeerbergenCommented:
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:
http://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
0
azamiCommented:
The book is "Developing for the Internet with Winsock" by Dave Roberts.
0
azamiCommented:
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!
0
coryderAuthor Commented:
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.
0
bertvermeerbergenCommented:
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.
0
coryderAuthor Commented:
i understand.  and thanks.  once again.
0
azamiCommented:
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.
0
Anju111599Commented:
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
0
coryderAuthor Commented:
azami, thx.  that's what i was trying yesterday.  still working on it.  still keeping all the options in mind.  thx all.  
0
coryderAuthor Commented:
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);
}
0
azamiCommented:
First some caveats - I haven't tested this code, partly for time and partly 'cuz I don't have your OS and compiler.  But it should help you get in the right direction.  Specifically, pipes are one-way, so you need two of them... I think that was the main point of failure in your code.  Another issue was that you closed handles before duping or using them.

Second, credit where it's due - I cribbed this from "Advanced Programming in the UNIX Environment" by W. Richard Stevens.

Third, EE is not the cleanest place to post code - so, of course, you'll have to clean this up a bit after you copy it.

Hope this helps!

---------------------------------------------------------------------
enum PIPES { READ = 0, WRITE = 1 };

int main()
{
      int h_child_stdin_pipe[2] = {0,0};
      int h_child_stdout_pipe[2] = {0,0};

      char buf[256] = {0};

      long flags = 0;

      pipe(h_child_stdin_pipe);
      pipe(h_child_stdout_pipe);

      int pid = fork();

      if (pid < 0)
      {
            // error
            cout << "fork error" << endl;
      }
      else if (pid == 0)
      {
            // child process

            //hook up stdin
            close(h_child_stdin_pipe[WRITE]);
            if (h_child_stdin_pipe[READ] != STDIN_FILENO)
            {
                  dup2(h_child_stdin_pipe[READ], STDIN_FILENO);      //Should check for error
                  close(h_child_stdin_pipe[READ]);
            }

            //hook up stdout
            close(h_child_stdout_pipe[READ]);
            if (h_child_stdout_pipe[WRITE] != STDOUT_FILENO)
            {
                  dup2(h_child_stdout_pipe[WRITE], STDOUT_FILENO);      //Should check for error
                  close(h_child_stdout_pipe[WRITE]);
            }

            //in theory, child inherits the new stdin and stdout
            execlp("ls", "", 0);
      }
      else if (pid > 0)
      {
            // parent

            //close what we ain't usin'
            close(h_child_stdin_pipe[READ]); //we'll be writing to other's stdin
            close(h_child_stdout_pipe[WRITE]); //we'll be reading from other's stdout

            read(h_child_stdout_pipe[READ], buf, 255);
            //write() to h_child_stdin_pipe[WRITE] to pass data to child's stdin
            
            printf("printf buf is: <%s>", buf);

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

            //clean up
            close(h_child_stdin_pipe[WRITE]);
            close(h_child_stdout_pipe[READ]);

            //NOTE - we set up both stdin and stdout for child, but we only
            //use stdout (i.e., we don't send commands to child process)
      }

      return(0);
}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
coryderAuthor Commented:
thanks.  that helped lots. =)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.