• C

Calling the standard ftp client from a C program

Hi,

I need to download files from a ftp server and I need to initiate it from
within a c program. I would like to avoid expect scripts and libexpect as it
might not be available.

How can I handle the password prompt from the server?
And then place the file where I want it?

One of the exec functions would be the best solution for my case.

Any good examples?
jeku_expertAsked:
Who is Participating?
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.

PaulCaswellCommented:
Is this Windoze? Here's a fragment of a tool I have for pushing and pulling files from/to an ftp site in a batch file. I am sure you could invoke batch files from C.

%TCPLogin% reads 'user <UserName> <Password>'

%IPAddress% is a normal ip address.

%FileRoot%.%DataFile% reads the name of the file expected at the target.

This one logs you on and leaves you at the 'ftp>' prompt.

echo %TCPLogin% >logon.txt
echo bin >>logon.txt
echo hash >>logon.txt
ftp -v -i -n -s:logon.txt %IPAddress%

This one will send a named file.

echo %TCPLogin% >senddat.txt
:echo bin >>senddat.txt
echo hash >>senddat.txt
echo cd incoming >>senddat.txt
echo put <FileName> %FileRoot%.%DataFile% >>senddat.txt
echo quit >>senddat.txt
ftp -v -i -n -s:senddat.txt %IPAddress%

Good luck.

Paul
0
PaulCaswellCommented:
This one gets a file from the site:

Settings as above.

echo %TCPLogin% >getrep.txt
echo bin >>getrep.txt
echo hash >>getrep.txt
echo cd outgoing >>getrep.txt
echo get <Remote File> <Local File> >>getrep.txt
echo quit >>getrep.txt
ftp -v -i -n -s:getrep.txt %IPAddress%

Paul
0
PaulCaswellCommented:
>>How can I handle the password prompt from the server?
There is one other password needed, thats the PPP password. Use something like:

rasdial %Connection% %PPPName% %PPPPass%

after building a Dial-Up-Networking connection called whatever %Connection% is set to.

Paul
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

jeku_expertAuthor Commented:
Sorry, I forgot to mention that I am devoloping under linux.
0
PaulCaswellCommented:
>>Sorry, I forgot to mention that I am devoloping under linux.
This question should probably be posted in the linux section then as they are all C gurus anyway.

Are the command-line parameters to 'ftp' simillar on linux? The technique may still work.

Paul
0
jeku_expertAuthor Commented:
My problem is that I can not use any external (to the C program) scripts.
That is why I should avoid scripts like expect. Maybe I should change this to
a linux question as you suggest. I am new with expers-exchange so I need to find out how to best use it!

PS. Thanks for the effort!
0
van_dyCommented:
Do you have libfetch availiable on your system?
0
jeku_expertAuthor Commented:
No, it does not look like I have that either...
0
van_dyCommented:
If it is availiable, it has calls  like
FILE *
     fetchGetFTP(struct url *u, struct url_stat *us, const char *flags);

and

FILE *
     fetchPutFTP(struct url *u, const char *flags);

take a look into the documentation and code it up a bit for a start.

hope this helps,
van_dy


0
van_dyCommented:

>>  No, it does not look like I have that either...

Hmm,
   in that case, it seems like you  are supposed to code up
a ftp client from scratch.
0
jeku_expertAuthor Commented:
I was hoping to just call the ftp client already available... And that should
be enough if I could find an easy way to give the client the password when he
asks for it...
0
van_dyCommented:
ohh thats simpler
0
van_dyCommented:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)         //argv[1] = server ip/name
{
      char command[100];
      strcpy(command, "ftp");
      strcat(command, " ");
      strcat(command, argv[1]);
      system(command);
      return 34;
}

wonder if something as simple will server ur purpose
0
jeku_expertAuthor Commented:
But no external scripts please.... :-)
Only standard linux functions like exec and similar.
0
PaulCaswellCommented:
>>if I could find an easy way to give the client the password when he asks for it
If the linux ftp client is like the Windoze one and van_dy's 'system' method works then you can pass the login name and password to ftp using the '-s:...' parameter like I do in my batch files.

Paul
0
jeku_expertAuthor Commented:
It would have worked if I could pass the password as a parameter to ftp.
Or sftp that I might use... But they do not accept password as a parameter, unless there is something I have misunderstood?
They always ask for it afterwards.
0
van_dyCommented:
please check out the autologin feature in you
ftp client.
.netrc in your home directory contains information
that will be used to autologin into a server.
a typical .netrc looks like
-------------

machine    10.2.1.38
                  login  somename
                password  mypassWORD

machine    10.6.2.56
                   login   someothername
                  password      someotherpassword
---------------------

now when you run somethign like
me@pc# ftp 10.6.2.56          
ftp will read .netrc to supply the user name and password as and when the server asks
without user intervention.this can be used  to code up something that might be useful
in your case.
0
van_dyCommented:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

int main(int argc, char **argv)
{
      FILE *fp = NULL;
      char string[100];
      int i = 0;


      fp = fopen(".netrc", "w");
      if(argc != 4){
            printf("Usage: %s <username> <password> <servip>\n", argv[0]);
            exit(1);
      }

/* setup netrc file */
      strcpy(string, "machine ");
      strcat(string, argv[3]);
      strcat(string, "\n");
      fputs(string, fp);
      strcpy(string, "\tlogin ");
      strcat(string, argv[1]);
      strcat(string, "\n");
      fputs(string, fp);
      strcpy(string, "\tpassword ");
      strcat(string, argv[2]);
      strcat(string, "\n");
      fputs(string, fp);
      fchmod(fileno(fp), 0600);
      fclose(fp);
/* setting up .netrc complete */

/* invoke ftp */
      strcpy(string, "ftp ");
      strcat(string, argv[3]);
      system(string);

// do something
      return 34;

      return 0;
}
0
jeku_expertAuthor Commented:
I think the type of solution I am looking for have to be something which does not require anything outside my c program. Password and username will be provided to me from a function call, but I can not expect to change the
configuration files or have any other script files. I think I need to read
"password:" from stdin and answer some way..
0
jkrCommented:
Check out
http://www.ibiblio.org/pub/Linux/libs/ftplib-3.1-bin-linux-i386.tar.gz ("callable libraries for doing FTP from within programs")
http://www.ibiblio.org/pub/Linux/libs/ftplib-3.1-src.tar.gz ("C callable libraries for doing FTP from within programs [src]")
0
fridomCEO/ProgrammerCommented:
Well how about using libcurl? You code would look like this:
http://curl.haxx.se/libcurl/

#include <stdio.h>
#include <curl/curl.h>



static int fetch_simple_page (CURL *curl){
      CURLcode res;
    FILE *my_file = fopen("LCC_README", "w");
      char simple_text_url [] = "ftp://ftp:someone.somwhere@www.q-software-solutions.com/pub/lcc/README";
      res = curl_easy_setopt(curl, CURLOPT_URL, simple_text_url);
    res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
    // res = curl_easy_setopt(curl, CURLOPT_VERBOSE);
      res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, my_file);
      res = curl_easy_perform(curl);
    fclose(my_file);
    return 1;
}


int main(void)
{
  CURL *curl;
  int irval = 0;


  curl = curl_easy_init();
  if(curl) {
    irval = fetch_simple_page(curl);
      if (irval){
      puts("Got the page");
       }


    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  curl_global_cleanup();
  return 0;
}

Clean, easy to understand and use. Passwords are not a problem just one option more, http,https and and and all there witht the same API, even the code i fetch simple page is not needed really just calling and what you get is put on the standard output a > to a file and it's in a file.

Seems to me the best solution.

Regards
Friedrich
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
PaulCaswellCommented:
Under Windoze you can spawn another task and open pipes to/from it. Is this opssible under linux?

Paul
0
jeku_expertAuthor Commented:
Thank you for the good advices. I will have to consider which of the three last option I will go for, but I think it will have to be one of them so I will split the points! Thanks!
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.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.