curl-library
A better poor telnet example (I can use I think)
Date: Mon, 19 May 2003 10:24:19 -0400
-----Original Message-----
From: Daniel Stenberg [mailto:daniel_at_haxx.se]
Sent: Friday, May 16, 2003 4:14 AM
To: libcurl Mailing list
Cc: Dan Leonard
Subject: Re: a poor telnet example -- but you don't have to enter the
password
On Thu, 15 May 2003, Dan Leonard wrote:
(Since this is a library-using app, I took this reply over to the
curl-library list.)
> I was trying to use the curl library for telnet where I don't have to
enter
> the password at a terminal; I do this because I want it to talk to a
router
> via an UI. I figured out a way, using "telnet://localhost", and a
write
> callback function. The biggest problem is that I have to assume the
socket
> connection back to the the telnetd daemon is "3", i.e. 0,1,2, are
stdin,
> stderr, stdout. This is a pretty good assumption, at least for a very
> short program.
>
> I see in 7.10 there might be ways of using "multi" to get file
desciptors,
> and to exit gracefully. This is a little new, as the system I am
working
> on is redhat 7.2 or 7.3, which has 7.9 curl naturally installed. I
guess I
> could install 7.10. Ayway, here is the poor example is attached.
>>libcurl's main paradigm is that it transfers files, either way. It is
not
>>very good at sending a little chunk now and little chunk then, as
telnet
>>requires.
>>To make libcurl more suitable for telnet, we should add two mechanisms
in the
>>API:
>> 1. Enable the application to tell the library that we have data to
send, or
>> that we don't have data to send. The current workings assume that
we will>>
>> continue sending data until there no longer is any, and then we're
done.
Yes, that's what I gathered.
>> 2. The reversed. Allow and application to tell the library that we
are not
>> prepared to receive any more data right now. The only kind of
>> flow-control an app has now, is to sleep in the callback before it
>> returns control back to the library and it certainly isn't very
nice.
>>In your telnet case, you could skip your work-around for file
descriptor 3 if
>>the first item in this list was added.
Yes. Actually I think I can use 7.8.1. By parsing through
/proc/<pid>/fd, you will always found "socket" at cnt six, after
".","..",stdin,stdio, stderr. Okay for my use, I'm going to just make a
system call.
Wondering now if I can capture more resposes and parse for some status
strings. either read(3,,,) or use write_data I should think.
I stll like using CURL because it does all protocols down to the
username. Making password work internally would help.
This version shuts-down gracefully by sending "quit\r" or "exit\r".
Dan
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include <errno.h>
#include <dirent.h>
#include <unistd.h>
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
static CURL *curl;
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
DIR * dp;
struct dirent *dirp;
int fd, bytes,cnt;
char dirs[128],dircmp[NAME_MAX], lbuf[2];
static long socketdno;
static char buflast;
static int madewrite = 0;
static int sockfdokay=0;
if ( size*nmemb == 0 )
return(0);
printf("%c", *(char *)buffer);
if ( *(char *)buffer == ' ' && buflast == ':' ) {
if ( !madewrite ) {
madewrite=1;
sprintf(dirs,"/proc/%d/fd",getpid());
dp = opendir(dirs);
dp = opendir(dirs);
if ( dp ) {
dirp = (struct dirent *)1;
for (cnt=0;dirp;) {
dirp = readdir(dp);
if ( dirp ) {
cnt++;
printf("dir is: %s cnt: %d\n",dirp->d_name,cnt);
sprintf(dirs,"/proc/%d/fd/%s",getpid(),dirp->d_name);
memset(dircmp,0,NAME_MAX);
if (readlink(dirs,dircmp,NAME_MAX) != -1 ) {
printf("link points to: %s\n", dircmp);
if ( !strncmp(dircmp,"socket:",strlen("socket:")) &&
cnt==6) {
printf("found socket at expected position: %d
link: %s\n",
cnt, dirp->d_name);
sockfdokay=1;
}
}
}
}
printf("fd dir count %d\n",cnt);
closedir(dp);
}
if ( cnt == 8 && sockfdokay == 1 ) { //
bytes = write(3,"CogcoG\r\r",strlen("CogcoG\r\r"));
printf("wrote: %d bytes sock: %d\n",bytes,3);
bytes = 1;
bytes = write(3,"who\r",strlen("who\r"));
printf("wrote: %d bytes sock: %d\n",bytes,3);
#if 0
while (bytes >0 ) {
bytes = read(3,lbuf,1);
printf("lub:: %c ::\n",lbuf);
}
#endif
bytes = write(3,"quit\r",strlen("quit\r"));
printf("wrote: %d bytes sock: %d\n",bytes,3);
bytes = write(3,"exit\r",strlen("exit\r"));
printf("wrote: %d bytes sock: %d\n",bytes,3);
}
}
}
buflast = *(char *)buffer;
/* printf("bytes in: %d\n",size*nmemb); */
return(size*nmemb);
}
//int main(int argc, char **argv)
int main()
{
FILE *hd_src;
int res;
curl = curl_easy_init();
/* Get curl 7.7 from sunet.se's FTP site: */
curl_easy_setopt(curl, CURLOPT_URL,
"telnet://localhost");
curl_easy_setopt(curl, CURLOPT_USERPWD, "COG:CogcoG");
curl_easy_setopt(curl, CURLOPT_VERBOSE, TRUE);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
res = curl_easy_perform(curl);
printf("res is: %d\n",res);
/* always cleanup */
curl_easy_cleanup(curl);
/* fclose(ftpfile); close the local file */
return 0;
}
-- Daniel Stenberg -- curl: been grokking URLs since 1998 ------------------------------------------------------- This SF.net email is sponsored by: If flattening out C++ or Java code to make your application fit in a relational database is painful, don't do it! Check out ObjectStore. Now part of Progress Software. http://www.objectstore.net/sourceforgeReceived on 2003-05-19